d89b3e
From 8518fbb314727cbb3f747c20ef194df7cd1bdac3 Mon Sep 17 00:00:00 2001
d89b3e
Message-Id: <8518fbb314727cbb3f747c20ef194df7cd1bdac3@dist-git>
d89b3e
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
d89b3e
Date: Wed, 28 Jan 2015 12:25:11 +0100
d89b3e
Subject: [PATCH] Split qemuDomainChrInsert into two parts
d89b3e
MIME-Version: 1.0
d89b3e
Content-Type: text/plain; charset=UTF-8
d89b3e
Content-Transfer-Encoding: 8bit
d89b3e
d89b3e
https://bugzilla.redhat.com/show_bug.cgi?id=1195155
d89b3e
d89b3e
Do the allocation first, then add the actual device.
d89b3e
The second part should never fail. This is good
d89b3e
for live hotplug where we don't want to remove the device
d89b3e
on OOM after the monitor command succeeded.
d89b3e
d89b3e
The only change in behavior is that on failure, the
d89b3e
vmdef->consoles array is freed, not just the first console.
d89b3e
d89b3e
(cherry picked from commit daf51be5f1b0f7b41c0813d43d6b66edfbe4f6d9)
d89b3e
Signed-off-by: Ján Tomko <jtomko@redhat.com>
d89b3e
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
d89b3e
---
d89b3e
 src/conf/domain_conf.c   | 18 +++++++++++++---
d89b3e
 src/conf/domain_conf.h   |  7 +++++--
d89b3e
 src/libvirt_private.syms |  3 ++-
d89b3e
 src/qemu/qemu_hotplug.c  | 54 +++++++++++++++++++++++++++++++++++++++++-------
d89b3e
 4 files changed, 68 insertions(+), 14 deletions(-)
d89b3e
d89b3e
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
d89b3e
index fed87f0..9bfffd0 100644
d89b3e
--- a/src/conf/domain_conf.c
d89b3e
+++ b/src/conf/domain_conf.c
d89b3e
@@ -11529,15 +11529,27 @@ virDomainChrGetDomainPtrs(const virDomainDef *vmdef,
d89b3e
 
d89b3e
 
d89b3e
 int
d89b3e
-virDomainChrInsert(virDomainDefPtr vmdef,
d89b3e
-                   virDomainChrDefPtr chr)
d89b3e
+virDomainChrPreAlloc(virDomainDefPtr vmdef,
d89b3e
+                     virDomainChrDefPtr chr)
d89b3e
 {
d89b3e
     virDomainChrDefPtr **arrPtr = NULL;
d89b3e
     size_t *cntPtr = NULL;
d89b3e
 
d89b3e
     virDomainChrGetDomainPtrsInternal(vmdef, chr->deviceType, &arrPtr, &cntPtr);
d89b3e
 
d89b3e
-    return VIR_APPEND_ELEMENT(*arrPtr, *cntPtr, chr);
d89b3e
+    return VIR_REALLOC_N(*arrPtr, *cntPtr + 1);
d89b3e
+}
d89b3e
+
d89b3e
+void
d89b3e
+virDomainChrInsertPreAlloced(virDomainDefPtr vmdef,
d89b3e
+                             virDomainChrDefPtr chr)
d89b3e
+{
d89b3e
+    virDomainChrDefPtr **arrPtr = NULL;
d89b3e
+    size_t *cntPtr = NULL;
d89b3e
+
d89b3e
+    virDomainChrGetDomainPtrsInternal(vmdef, chr->deviceType, &arrPtr, &cntPtr);
d89b3e
+
d89b3e
+    ignore_value(VIR_APPEND_ELEMENT_INPLACE(*arrPtr, *cntPtr, chr));
d89b3e
 }
d89b3e
 
d89b3e
 virDomainChrDefPtr
d89b3e
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
d89b3e
index b912845..1436eb8 100644
d89b3e
--- a/src/conf/domain_conf.h
d89b3e
+++ b/src/conf/domain_conf.h
d89b3e
@@ -2543,8 +2543,11 @@ bool
d89b3e
 virDomainChrEquals(virDomainChrDefPtr src,
d89b3e
                    virDomainChrDefPtr tgt);
d89b3e
 int
d89b3e
-virDomainChrInsert(virDomainDefPtr vmdef,
d89b3e
-                   virDomainChrDefPtr chr);
d89b3e
+virDomainChrPreAlloc(virDomainDefPtr vmdef,
d89b3e
+                     virDomainChrDefPtr chr);
d89b3e
+void
d89b3e
+virDomainChrInsertPreAlloced(virDomainDefPtr vmdef,
d89b3e
+                             virDomainChrDefPtr chr);
d89b3e
 virDomainChrDefPtr
d89b3e
 virDomainChrRemove(virDomainDefPtr vmdef,
d89b3e
                    virDomainChrDefPtr chr);
d89b3e
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
d89b3e
index 325a912..18c715a 100644
d89b3e
--- a/src/libvirt_private.syms
d89b3e
+++ b/src/libvirt_private.syms
d89b3e
@@ -153,7 +153,8 @@ virDomainChrDefNew;
d89b3e
 virDomainChrEquals;
d89b3e
 virDomainChrFind;
d89b3e
 virDomainChrGetDomainPtrs;
d89b3e
-virDomainChrInsert;
d89b3e
+virDomainChrInsertPreAlloced;
d89b3e
+virDomainChrPreAlloc;
d89b3e
 virDomainChrRemove;
d89b3e
 virDomainChrSerialTargetTypeFromString;
d89b3e
 virDomainChrSerialTargetTypeToString;
d89b3e
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
d89b3e
index 8a3eb27..00ce77f 100644
d89b3e
--- a/src/qemu/qemu_hotplug.c
d89b3e
+++ b/src/qemu/qemu_hotplug.c
d89b3e
@@ -1390,9 +1390,9 @@ int qemuDomainAttachRedirdevDevice(virQEMUDriverPtr driver,
d89b3e
 
d89b3e
 }
d89b3e
 
d89b3e
-int
d89b3e
-qemuDomainChrInsert(virDomainDefPtr vmdef,
d89b3e
-                    virDomainChrDefPtr chr)
d89b3e
+static int
d89b3e
+qemuDomainChrPreInsert(virDomainDefPtr vmdef,
d89b3e
+                       virDomainChrDefPtr chr)
d89b3e
 {
d89b3e
     if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
d89b3e
         chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) {
d89b3e
@@ -1407,25 +1407,63 @@ qemuDomainChrInsert(virDomainDefPtr vmdef,
d89b3e
         return -1;
d89b3e
     }
d89b3e
 
d89b3e
-    if (virDomainChrInsert(vmdef, chr) < 0)
d89b3e
+    if (virDomainChrPreAlloc(vmdef, chr) < 0)
d89b3e
         return -1;
d89b3e
 
d89b3e
     /* Due to some crazy backcompat stuff, the first serial device is an alias
d89b3e
      * to the first console too. If this is the case, the definition must be
d89b3e
      * duplicated as first console device. */
d89b3e
-    if (vmdef->nserials == 1 && vmdef->nconsoles == 0) {
d89b3e
-        if ((!vmdef->consoles && VIR_ALLOC(vmdef->consoles) < 0) ||
d89b3e
-            VIR_ALLOC(vmdef->consoles[0]) < 0) {
d89b3e
-            virDomainChrRemove(vmdef, chr);
d89b3e
+    if (vmdef->nserials == 0 && vmdef->nconsoles == 0 &&
d89b3e
+        chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
d89b3e
+        if (!vmdef->consoles && VIR_ALLOC(vmdef->consoles) < 0)
d89b3e
+            return -1;
d89b3e
+
d89b3e
+        if (VIR_ALLOC(vmdef->consoles[0]) < 0) {
d89b3e
+            VIR_FREE(vmdef->consoles);
d89b3e
             return -1;
d89b3e
         }
d89b3e
+        vmdef->nconsoles++;
d89b3e
+    }
d89b3e
+    return 0;
d89b3e
+}
d89b3e
+
d89b3e
+static void
d89b3e
+qemuDomainChrInsertPreAlloced(virDomainDefPtr vmdef,
d89b3e
+                              virDomainChrDefPtr chr)
d89b3e
+{
d89b3e
+    virDomainChrInsertPreAlloced(vmdef, chr);
d89b3e
+    if (vmdef->nserials == 1 && vmdef->nconsoles == 0 &&
d89b3e
+        chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
d89b3e
         vmdef->nconsoles = 1;
d89b3e
 
d89b3e
         /* Create an console alias for the serial port */
d89b3e
         vmdef->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
d89b3e
         vmdef->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
d89b3e
     }
d89b3e
+}
d89b3e
 
d89b3e
+static void
d89b3e
+qemuDomainChrInsertPreAllocCleanup(virDomainDefPtr vmdef,
d89b3e
+                                   virDomainChrDefPtr chr)
d89b3e
+{
d89b3e
+    /* Remove the stub console added by qemuDomainChrPreInsert */
d89b3e
+    if (vmdef->nserials == 0 && vmdef->nconsoles == 1 &&
d89b3e
+        chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
d89b3e
+        VIR_FREE(vmdef->consoles[0]);
d89b3e
+        VIR_FREE(vmdef->consoles);
d89b3e
+        vmdef->nconsoles = 0;
d89b3e
+    }
d89b3e
+}
d89b3e
+
d89b3e
+int
d89b3e
+qemuDomainChrInsert(virDomainDefPtr vmdef,
d89b3e
+                    virDomainChrDefPtr chr)
d89b3e
+{
d89b3e
+    if (qemuDomainChrPreInsert(vmdef, chr) < 0) {
d89b3e
+        qemuDomainChrInsertPreAllocCleanup(vmdef, chr);
d89b3e
+        return -1;
d89b3e
+    }
d89b3e
+    qemuDomainChrInsertPreAlloced(vmdef, chr);
d89b3e
     return 0;
d89b3e
 }
d89b3e
 
d89b3e
-- 
d89b3e
2.3.0
d89b3e