If present, prefer the file descriptor created earlier
instead of creating one in a qemuBuild function.
Signed-off-by: Ján Tomko <jtomko(a)redhat.com>
---
src/qemu/qemu_command.c | 23 +++------
src/qemu/qemu_process.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 133 insertions(+), 17 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 25ea127095..54a1a299e2 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5058,7 +5058,7 @@ enum {
* host side of the character device */
static char *
qemuBuildChrChardevStr(virLogManagerPtr logManager,
- virSecurityManagerPtr secManager,
+ virSecurityManagerPtr secManager ATTRIBUTE_UNUSED,
virCommandPtr cmd,
virQEMUDriverConfigPtr cfg,
const virDomainDef *def,
@@ -5195,22 +5195,11 @@ qemuBuildChrChardevStr(virLogManagerPtr logManager,
case VIR_DOMAIN_CHR_TYPE_UNIX:
virBufferAsprintf(&buf, "socket,id=%s", charAlias);
- if (dev->data.nix.listen &&
- (flags & QEMU_BUILD_CHARDEV_UNIX_FD_PASS) &&
- virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS)) {
- if (qemuSecuritySetSocketLabel(secManager, (virDomainDefPtr)def) < 0)
- goto cleanup;
- int fd = qemuOpenChrChardevUNIXSocket(dev);
- if (qemuSecurityClearSocketLabel(secManager, (virDomainDefPtr)def) < 0) {
- VIR_FORCE_CLOSE(fd);
- goto cleanup;
- }
- if (fd < 0)
- goto cleanup;
-
- virBufferAsprintf(&buf, ",fd=%d", fd);
-
- virCommandPassFD(cmd, fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+ if (chrSourcePriv &&
+ chrSourcePriv->fd != -1) {
+ virBufferAsprintf(&buf, ",fd=%d", chrSourcePriv->fd);
+ virCommandPassFD(cmd, chrSourcePriv->fd,
VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+ chrSourcePriv->fd = -1;
} else {
virBufferAddLit(&buf, ",path=");
virQEMUBuildBufferEscapeComma(&buf, dev->data.nix.path);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 77b7464436..f315d28dd0 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6136,6 +6136,127 @@ qemuProcessOpenVhostVsock(virDomainVsockDefPtr vsock)
}
+static int
+qemuProcessMaybeOpenChrSource(virDomainObjPtr vm,
+ const virDomainChrSourceDef *src)
+{
+ qemuDomainChrSourcePrivatePtr srcPriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(src);
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ virQEMUDriverPtr driver = priv->driver;
+ virQEMUCapsPtr qemuCaps = priv->qemuCaps;
+ int fd = -1;
+ int ret = -1;
+
+ if (src->type != VIR_DOMAIN_CHR_TYPE_UNIX)
+ return 0;
+
+ if (!src->data.nix.listen)
+ return 0;
+
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS))
+ return 0;
+
+ if (qemuSecuritySetSocketLabel(driver->securityManager, vm->def) < 0)
+ goto cleanup;
+ fd = qemuOpenChrChardevUNIXSocket(src);
+ if (qemuSecurityClearSocketLabel(driver->securityManager, vm->def) < 0)
+ goto cleanup;
+
+ if (fd < 0)
+ goto cleanup;
+
+ srcPriv->fd = fd;
+ fd = -1;
+ ret = 0;
+
+ cleanup:
+ VIR_FORCE_CLOSE(fd);
+ return ret;
+}
+
+
+static int
+qemuProcessPrepareChrFDs(virDomainObjPtr vm,
+ virDomainDefPtr def)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int ret = -1;
+ size_t i;
+
+ if (priv->monConfig) {
+ if (qemuProcessMaybeOpenChrSource(vm, priv->monConfig) < 0)
+ goto cleanup;
+ }
+
+ /* VIR_DOMAIN_NET_TYPE_VHOSTUSER can be backed by a chardev
+ * but FD passing does not work, see commit ed5aa85f3 */
+
+ for (i = 0; i < def->nsmartcards; i++) {
+ virDomainSmartcardDefPtr smartcard = def->smartcards[i];
+ if (smartcard->type != VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH)
+ continue;
+ if (qemuProcessMaybeOpenChrSource(vm, smartcard->data.passthru) < 0)
+ goto cleanup;
+ }
+
+ /* Shmems can also have a chardev source, but the listen mode is
+ * set to false in the XML parser. Nothing to do here */
+
+ for (i = 0; i < def->nserials; i++) {
+ virDomainChrDefPtr serial = def->serials[i];
+ if (qemuProcessMaybeOpenChrSource(vm, serial->source) < 0)
+ goto cleanup;
+ }
+
+ for (i = 0; i < def->nparallels; i++) {
+ virDomainChrDefPtr parallel = def->parallels[i];
+ if (qemuProcessMaybeOpenChrSource(vm, parallel->source) < 0)
+ goto cleanup;
+ }
+
+ for (i = 0; i < def->nchannels; i++) {
+ virDomainChrDefPtr channel = def->channels[i];
+ if (channel->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD
&&
+ channel->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO)
+ continue;
+ if (qemuProcessMaybeOpenChrSource(vm, channel->source) < 0)
+ goto cleanup;
+ }
+
+ for (i = 0; i < def->nconsoles; i++) {
+ virDomainChrDefPtr console = def->consoles[i];
+ if (console->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
+ continue;
+ if (qemuProcessMaybeOpenChrSource(vm, console->source) < 0)
+ goto cleanup;
+ }
+
+ for (i = 0; i < def->nredirdevs; i++) {
+ virDomainRedirdevDefPtr redirdev = def->redirdevs[i];
+ if (qemuProcessMaybeOpenChrSource(vm, redirdev->source) < 0)
+ goto cleanup;
+ }
+
+ for (i = 0; i < def->nrngs; i++) {
+ virDomainRNGDefPtr rng = def->rngs[i];
+ switch ((virDomainRNGBackend) rng->backend) {
+ case VIR_DOMAIN_RNG_BACKEND_RANDOM:
+ case VIR_DOMAIN_RNG_BACKEND_LAST:
+ /* no chardev backend is needed */
+ return 0;
+
+ case VIR_DOMAIN_RNG_BACKEND_EGD:
+ if (qemuProcessMaybeOpenChrSource(vm, rng->source.chardev) < 0)
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+ cleanup:
+ return ret;
+}
+
+
/**
* qemuProcessPrepareHost:
* @driver: qemu driver
@@ -6228,6 +6349,9 @@ qemuProcessPrepareHost(virQEMUDriverPtr driver,
qemuProcessMakeDir(driver, vm, priv->channelTargetDir) < 0)
goto cleanup;
+ if (qemuProcessPrepareChrFDs(vm, vm->def) < 0)
+ goto cleanup;
+
VIR_DEBUG("Write domain masterKey");
if (qemuDomainWriteMasterKeyFile(driver, vm) < 0)
goto cleanup;
@@ -6886,6 +7010,9 @@ qemuProcessCreatePretendCmd(virQEMUDriverPtr driver,
if (qemuProcessPrepareDomain(driver, vm, flags) < 0)
goto cleanup;
+ if (qemuProcessPrepareChrFDs(vm, vm->def) < 0)
+ goto cleanup;
+
VIR_DEBUG("Building emulator command line");
cmd = qemuBuildCommandLine(driver,
NULL,
--
2.16.4