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