]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Add ability to abort existing console while creating new one
authorPeter Krempa <pkrempa@redhat.com>
Thu, 6 Oct 2011 10:24:47 +0000 (12:24 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 27 Feb 2012 14:05:17 +0000 (15:05 +0100)
This patch fixes console corruption, that happens if two concurrent
sessions are opened for a single console on a domain. Result of this
corruption was that each of the console streams recieved just a part
of the data written to the pipe so every console rendered unusable.

New helper function for safe console handling is used to establish the
console stream connection. This function ensures that no other libvirt
client is using the console (with the ability to disconnect consoles of
libvirt clients) and that no UUCP style lockfile is placed on the PTY
device.

* src/qemu/qemu_domain.h
        - add data structure to domain's private data dealing with
          console connections
* src/qemu/qemu_domain.c:
        - allocate/free domain's console data structure
* src/qemu/qemu_driver.c
        - use the new helper function for console handling

src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_driver.c

index 01e558089326356e4561b6fe87f41c373a28f628..2fed91ed6ba12e09b94fd1cd148a131dffb38df4 100644 (file)
@@ -192,6 +192,9 @@ static void *qemuDomainObjPrivateAlloc(void)
     if (qemuDomainObjInitJob(priv) < 0)
         goto error;
 
+    if (!(priv->cons = virConsoleAlloc()))
+        goto error;
+
     priv->migMaxBandwidth = QEMU_DOMAIN_DEFAULT_MIG_BANDWIDTH_MAX;
 
     return priv;
@@ -214,6 +217,8 @@ static void qemuDomainObjPrivateFree(void *data)
     VIR_FREE(priv->lockState);
     VIR_FREE(priv->origname);
 
+    virConsoleFree(priv->cons);
+
     /* This should never be non-NULL if we get here, but just in case... */
     if (priv->mon) {
         VIR_ERROR(_("Unexpected QEMU monitor still active during domain deletion"));
index 222d80e400cd2a8621650444631dfd51e0d957a9..1333d8cd7c0bf5ab58b882f003f746d9e9783385 100644 (file)
@@ -30,6 +30,7 @@
 # include "qemu_agent.h"
 # include "qemu_conf.h"
 # include "bitmap.h"
+# include "virconsole.h"
 
 # define QEMU_EXPECTED_VIRT_TYPES      \
     ((1 << VIR_DOMAIN_VIRT_QEMU) |     \
@@ -127,6 +128,8 @@ struct _qemuDomainObjPrivate {
 
     unsigned long migMaxBandwidth;
     char *origname;
+
+    virConsolesPtr cons;
 };
 
 struct qemuDomainWatchdogEvent
index f37f1583ac1ca33c8b98fda3260a6681db2953d8..a3ba5337ac32755badfd7574e37fd28672e21caf 100644 (file)
@@ -11244,8 +11244,10 @@ qemuDomainOpenConsole(virDomainPtr dom,
     int ret = -1;
     int i;
     virDomainChrDefPtr chr = NULL;
+    qemuDomainObjPrivatePtr priv;
 
-    virCheckFlags(0, -1);
+    virCheckFlags(VIR_DOMAIN_CONSOLE_SAFE |
+                  VIR_DOMAIN_CONSOLE_FORCE, -1);
 
     qemuDriverLock(driver);
     virUUIDFormat(dom->uuid, uuidstr);
@@ -11262,6 +11264,8 @@ qemuDomainOpenConsole(virDomainPtr dom,
         goto cleanup;
     }
 
+    priv = vm->privateData;
+
     if (dev_name) {
         for (i = 0 ; !chr && i < vm->def->nconsoles ; i++) {
             if (vm->def->consoles[i]->info.alias &&
@@ -11297,11 +11301,18 @@ qemuDomainOpenConsole(virDomainPtr dom,
         goto cleanup;
     }
 
-    if (virFDStreamOpenFile(st, chr->source.data.file.path,
-                            0, 0, O_RDWR) < 0)
-        goto cleanup;
+    /* handle mutually exclusive access to console devices */
+    ret = virConsoleOpen(priv->cons,
+                         chr->source.data.file.path,
+                         st,
+                         (flags & VIR_DOMAIN_CONSOLE_FORCE) != 0);
+
+    if (ret == 1) {
+        qemuReportError(VIR_ERR_OPERATION_FAILED,
+                        _("Active console session exists for this domain"));
+        ret = -1;
+    }
 
-    ret = 0;
 cleanup:
     if (vm)
         virDomainObjUnlock(vm);