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 did recieve just a part of the data written to the pipe so every console rendered unusable. This patch adds a check that verifies if an open console exists and notifies the user. This patch also adds support for the flag VIR_DOMAIN_CONSOLE_FORCE that interrupts the existing session before creating a new one. This serves as a fallback if an AFK admin holds the console or a connection breaks. --- src/qemu/qemu_domain.c | 3 +++ src/qemu/qemu_domain.h | 2 ++ src/qemu/qemu_driver.c | 23 ++++++++++++++++++++++- 3 files changed, 27 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 85bebd6..be316b6 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -233,6 +233,9 @@ static void qemuDomainObjPrivateFree(void *data) VIR_FREE(priv->lockState); VIR_FREE(priv->origname); + if (priv->console) + virStreamFree(priv->console); + /* 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")); diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index d9f323c..e32f4ef 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -127,6 +127,8 @@ struct _qemuDomainObjPrivate { unsigned long migMaxBandwidth; char *origname; + + virStreamPtr console; }; struct qemuDomainWatchdogEvent diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ec01cd5..3b0cb70 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10394,8 +10394,10 @@ qemuDomainOpenConsole(virDomainPtr dom, int ret = -1; int i; virDomainChrDefPtr chr = NULL; + qemuDomainObjPrivatePtr priv; - virCheckFlags(0, -1); + virCheckFlags(VIR_DOMAIN_CONSOLE_TRY | + VIR_DOMAIN_CONSOLE_FORCE, -1); qemuDriverLock(driver); virUUIDFormat(dom->uuid, uuidstr); @@ -10412,6 +10414,8 @@ qemuDomainOpenConsole(virDomainPtr dom, goto cleanup; } + priv = vm->privateData; + if (dev_name) { if (vm->def->console && STREQ(dev_name, vm->def->console->info.alias)) @@ -10445,10 +10449,27 @@ qemuDomainOpenConsole(virDomainPtr dom, goto cleanup; } + /* kill open console stream */ + if (priv->console) { + if (virFDStreamIsOpen(priv->console) && + !(flags & VIR_DOMAIN_CONSOLE_FORCE)) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + _("Active console session exists for this domain")); + goto cleanup; + } + + virStreamAbort(priv->console); + virStreamFree(priv->console); + priv->console = NULL; + } + if (virFDStreamOpenFile(st, chr->source.data.file.path, 0, 0, O_RDWR) < 0) goto cleanup; + virStreamRef(st); + priv->console = st; + ret = 0; cleanup: if (vm) -- 1.7.3.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list