[PATCH 14/27] qemu: Rewrite chardev startup code to use qemuFDPass

Peter Krempa pkrempa at redhat.com
Wed Feb 9 16:02:06 UTC 2022


Rewrite the parts which already pass FDs via fdset or directly to use
the new infrastructure.

Apart from simpler code this also adds the appropriate names to the fds
in the fdsets which will allow us to properly remove the fdsets won
hot-unplug of chardevs, which we didn't do for now and resulted in
leaking the FDs.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 src/qemu/qemu_command.c                       | 74 ++++---------------
 src/qemu/qemu_domain.c                        | 11 +--
 src/qemu/qemu_domain.h                        |  8 +-
 src/qemu/qemu_process.c                       | 42 +++++++++--
 .../qemuxml2argvdata/aarch64-pci-serial.args  |  4 +-
 .../name-escape.x86_64-2.11.0.args            |  4 +-
 .../name-escape.x86_64-latest.args            |  4 +-
 .../qemuxml2argvdata/serial-file-chardev.args |  4 +-
 .../serial-file-chardev.x86_64-latest.args    |  4 +-
 tests/qemuxml2argvdata/serial-file-log.args   |  6 +-
 .../serial-file-log.x86_64-latest.args        |  6 +-
 .../qemuxml2argvdata/serial-many-chardev.args |  4 +-
 .../serial-many-chardev.x86_64-latest.args    |  4 +-
 tests/qemuxml2argvtest.c                      | 56 ++++++++------
 14 files changed, 108 insertions(+), 123 deletions(-)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 6667433616..9a51a373b0 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -301,23 +301,6 @@ qemuBuildMasterKeyCommandLine(virCommand *cmd,
 }


-/**
- * qemuBuildFDSet:
- * @fd: fd to reassign to the child
- * @idx: index in the fd set
- *
- * Format the parameters for the -add-fd command line option
- * for the given file descriptor. The file descriptor must previously
- * have been 'transferred' in a virCommandPassFDIndex() call,
- * and @idx is the value returned by that call.
- */
-static char *
-qemuBuildFDSet(int fd, size_t idx)
-{
-    return g_strdup_printf("set=%zu,fd=%d", idx, fd);
-}
-
-
 /**
  * qemuVirCommandGetFDSet:
  * @cmd: the command to modify
@@ -1362,8 +1345,8 @@ qemuBuildChardevStr(const virDomainChrSourceDef *dev,
         path = dev->data.file.path;
         append = dev->data.file.append;

-        if (chrSourcePriv->fdset) {
-            path = chrSourcePriv->fdset;
+        if (chrSourcePriv->sourcefd) {
+            path = qemuFDPassGetPath(chrSourcePriv->sourcefd);
             append = VIR_TRISTATE_SWITCH_ON;
         }

@@ -1430,8 +1413,8 @@ qemuBuildChardevStr(const virDomainChrSourceDef *dev,

     case VIR_DOMAIN_CHR_TYPE_UNIX:
         virBufferAsprintf(&buf, "socket,id=%s", charAlias);
-        if (chrSourcePriv->passedFD != -1) {
-            virBufferAsprintf(&buf, ",fd=%d", chrSourcePriv->passedFD);
+        if (chrSourcePriv->sourcefd) {
+            virBufferAsprintf(&buf, ",fd=%s", qemuFDPassGetPath(chrSourcePriv->sourcefd));
         } else {
             virBufferAddLit(&buf, ",path=");
             virQEMUBuildBufferEscapeComma(&buf, dev->data.nix.path);
@@ -1466,8 +1449,8 @@ qemuBuildChardevStr(const virDomainChrSourceDef *dev,
         path = dev->logfile;
         append = dev->logappend;

-        if (chrSourcePriv->logFdset) {
-            path = chrSourcePriv->logFdset;
+        if (chrSourcePriv->logfd) {
+            path = qemuFDPassGetPath(chrSourcePriv->logfd);
             append = VIR_TRISTATE_SWITCH_ON;
         }

@@ -1527,28 +1510,8 @@ qemuBuildChardevCommand(virCommand *cmd,
         break;

     case VIR_DOMAIN_CHR_TYPE_FILE:
-        if (chrSourcePriv->fd != -1) {
-            g_autofree char *fdset = NULL;
-            size_t idx;
-
-            virCommandPassFDIndex(cmd, chrSourcePriv->fd,
-                                  VIR_COMMAND_PASS_FD_CLOSE_PARENT, &idx);
-            fdset = qemuBuildFDSet(chrSourcePriv->fd, idx);
-            chrSourcePriv->fd = -1;
-
-            virCommandAddArg(cmd, "-add-fd");
-            virCommandAddArg(cmd, fdset);
-
-            chrSourcePriv->fdset = g_strdup_printf("/dev/fdset/%zu", idx);
-        }
-        break;
-
     case VIR_DOMAIN_CHR_TYPE_UNIX:
-        if (chrSourcePriv->fd != -1) {
-            virCommandPassFD(cmd, chrSourcePriv->fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
-            chrSourcePriv->passedFD = chrSourcePriv->fd;
-            chrSourcePriv->fd = -1;
-        }
+        qemuFDPassTransferCommand(chrSourcePriv->sourcefd, cmd);
         break;

     case VIR_DOMAIN_CHR_TYPE_NULL:
@@ -1571,20 +1534,7 @@ qemuBuildChardevCommand(virCommand *cmd,
         return -1;
     }

-    if (chrSourcePriv->logfd != -1) {
-        g_autofree char *fdset = NULL;
-        size_t idx;
-
-        virCommandPassFDIndex(cmd, chrSourcePriv->logfd,
-                              VIR_COMMAND_PASS_FD_CLOSE_PARENT, &idx);
-        fdset = qemuBuildFDSet(chrSourcePriv->logfd, idx);
-        chrSourcePriv->logfd = -1;
-
-        virCommandAddArg(cmd, "-add-fd");
-        virCommandAddArg(cmd, fdset);
-
-        chrSourcePriv->logFdset = g_strdup_printf("/dev/fdset/%zu", idx);
-    }
+    qemuFDPassTransferCommand(chrSourcePriv->logfd, cmd);

     if (!(charstr = qemuBuildChardevStr(dev, charAlias)))
         return -1;
@@ -5001,8 +4951,12 @@ qemuBuildVideoCommandLine(virCommand *cmd,
             qemuDomainChrSourcePrivate *chrsrcpriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(chrsrc);

             chrsrc->type = VIR_DOMAIN_CHR_TYPE_UNIX;
-            chrsrcpriv->fd = videopriv->vhost_user_fd;
-            videopriv->vhost_user_fd = -1;
+            chrsrcpriv->sourcefd = qemuFDPassNew(video->info.alias, priv, false);
+
+            if (qemuFDPassAddFD(chrsrcpriv->sourcefd,
+                                &videopriv->vhost_user_fd,
+                                "-vhost-user") < 0)
+                return -1;

             if (qemuBuildChardevCommand(cmd, chrsrc, chrAlias, priv->qemuCaps) < 0)
                 return -1;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index d0abf76e4a..5483e0720f 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -904,11 +904,6 @@ qemuDomainChrSourcePrivateNew(void)
     if (!(priv = virObjectNew(qemuDomainChrSourcePrivateClass)))
         return NULL;

-    priv->fd = -1;
-    priv->logfd = -1;
-
-    priv->passedFD = -1;
-
     return (virObject *) priv;
 }

@@ -918,13 +913,11 @@ qemuDomainChrSourcePrivateDispose(void *obj)
 {
     qemuDomainChrSourcePrivate *priv = obj;

-    VIR_FORCE_CLOSE(priv->fd);
-    VIR_FORCE_CLOSE(priv->logfd);
+    qemuFDPassFree(priv->sourcefd);
+    qemuFDPassFree(priv->logfd);

     g_free(priv->tlsCertPath);

-    g_free(priv->fdset);
-    g_free(priv->logFdset);
     g_free(priv->tlsCredsAlias);

     g_clear_pointer(&priv->secinfo, qemuDomainSecretInfoFree);
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index b7d0f5d2d5..e9901cb5c3 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -36,6 +36,7 @@
 #include "qemu_capabilities.h"
 #include "qemu_migration_params.h"
 #include "qemu_slirp.h"
+#include "qemu_fd.h"
 #include "virmdev.h"
 #include "virchrdev.h"
 #include "virobject.h"
@@ -347,16 +348,13 @@ struct _qemuDomainChrSourcePrivate {
      * NB: *not* to be written to qemu domain object XML */
     qemuDomainSecretInfo *secinfo;

-    int fd; /* file descriptor of the chardev source */
-    int logfd; /* file descriptor of the logging source */
+    qemuFDPass *sourcefd;
+    qemuFDPass *logfd;
     bool wait; /* wait for incoming connections on chardev */

     char *tlsCertPath; /* path to certificates if TLS is requested */
     bool tlsVerify; /* whether server should verify client certificates */

-    char *fdset; /* fdset path corresponding to the passed filedescriptor */
-    char *logFdset; /* fdset path corresponding to the passed filedescriptor for logfile */
-    int passedFD; /* filedescriptor number when fdset passing it directly */
     char *tlsCredsAlias; /* alias of the x509 tls credentials object */
 };

diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 0e17e1bf94..b44e684589 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6809,6 +6809,7 @@ struct qemuProcessPrepareHostBackendChardevData {
     virLogManager *logManager;
     virQEMUDriverConfig *cfg;
     virDomainDef *def;
+    const char *fdprefix;
 };


@@ -6819,10 +6820,14 @@ qemuProcessPrepareHostBackendChardevOne(virDomainDeviceDef *dev,
 {
     struct qemuProcessPrepareHostBackendChardevData *data = opaque;
     qemuDomainChrSourcePrivate *charpriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(chardev);
+    const char *devalias = NULL;

     /* this function is also called for the monitor backend which doesn't have
      * a 'dev' */
     if (dev) {
+        virDomainDeviceInfo *info = virDomainDeviceGetInfo(dev);
+        devalias = info->alias;
+
         /* vhost-user disk doesn't use FD passing */
         if (dev->type == VIR_DOMAIN_DEVICE_DISK)
             return 0;
@@ -6836,6 +6841,8 @@ qemuProcessPrepareHostBackendChardevOne(virDomainDeviceDef *dev,
         /* TPMs FD passing setup is special and handled separately */
         if (dev->type == VIR_DOMAIN_DEVICE_TPM)
             return 0;
+    } else {
+        devalias = data->fdprefix;
     }

     switch ((virDomainChrType) chardev->type) {
@@ -6851,33 +6858,43 @@ qemuProcessPrepareHostBackendChardevOne(virDomainDeviceDef *dev,
     case VIR_DOMAIN_CHR_TYPE_SPICEPORT:
         break;

-    case VIR_DOMAIN_CHR_TYPE_FILE:
+    case VIR_DOMAIN_CHR_TYPE_FILE: {
+        VIR_AUTOCLOSE sourcefd = -1;
+
         if (qemuProcessPrepareHostBackendChardevFileHelper(chardev->data.file.path,
                                                            chardev->data.file.append,
-                                                           &charpriv->fd,
+                                                           &sourcefd,
                                                            data->logManager,
                                                            data->priv->driver->securityManager,
                                                            data->cfg,
                                                            data->def) < 0)
             return -1;

+        charpriv->sourcefd = qemuFDPassNew(devalias, data->priv, true);
+
+        if (qemuFDPassAddFD(charpriv->sourcefd, &sourcefd, "-source") < 0)
+            return -1;
+    }
         break;

     case VIR_DOMAIN_CHR_TYPE_UNIX:
         if (chardev->data.nix.listen &&
             virQEMUCapsGet(data->priv->qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS_COMMANDLINE)) {
+            VIR_AUTOCLOSE sourcefd = -1;

             if (qemuSecuritySetSocketLabel(data->priv->driver->securityManager, data->def) < 0)
                 return -1;

-            charpriv->fd = qemuOpenChrChardevUNIXSocket(chardev);
+            sourcefd = qemuOpenChrChardevUNIXSocket(chardev);

-            if (qemuSecurityClearSocketLabel(data->priv->driver->securityManager, data->def) < 0) {
-                VIR_FORCE_CLOSE(charpriv->fd);
+            if (qemuSecurityClearSocketLabel(data->priv->driver->securityManager, data->def) < 0 ||
+                sourcefd < 0)
                 return -1;
-            }

-            if (charpriv->fd < 0)
+            /* UNIX socket use direct FD passing */
+            charpriv->sourcefd = qemuFDPassNew(devalias, data->priv, false);
+
+            if (qemuFDPassAddFD(charpriv->sourcefd, &sourcefd, "-source") < 0)
                 return -1;
         }
         break;
@@ -6892,14 +6909,21 @@ qemuProcessPrepareHostBackendChardevOne(virDomainDeviceDef *dev,
     }

     if (chardev->logfile) {
+        VIR_AUTOCLOSE logfd = -1;
+
         if (qemuProcessPrepareHostBackendChardevFileHelper(chardev->logfile,
                                                            chardev->logappend,
-                                                           &charpriv->logfd,
+                                                           &logfd,
                                                            data->logManager,
                                                            data->priv->driver->securityManager,
                                                            data->cfg,
                                                            data->def) < 0)
             return -1;
+
+        charpriv->logfd = qemuFDPassNew(devalias, data->priv, true);
+
+        if (qemuFDPassAddFD(charpriv->logfd, &logfd, "-log") < 0)
+            return -1;
     }

     return 0;
@@ -6932,6 +6956,8 @@ qemuProcessPrepareHostBackendChardev(virDomainObj *vm)
                                               &data) < 0)
         return -1;

+    data.fdprefix = "monitor";
+
     if (qemuProcessPrepareHostBackendChardevOne(NULL, priv->monConfig, &data) < 0)
         return -1;

diff --git a/tests/qemuxml2argvdata/aarch64-pci-serial.args b/tests/qemuxml2argvdata/aarch64-pci-serial.args
index aca88e8e60..e012ea24dd 100644
--- a/tests/qemuxml2argvdata/aarch64-pci-serial.args
+++ b/tests/qemuxml2argvdata/aarch64-pci-serial.args
@@ -29,7 +29,7 @@ QEMU_AUDIO_DRV=none \
 -device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1 \
 -device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \
 -device pcie-root-port,port=16,chassis=3,id=pci.3,bus=pcie.0,addr=0x2 \
--add-fd set=0,fd=1751 \
--chardev pty,id=charserial0,logfile=/dev/fdset/0,logappend=on \
+-add-fd set=1,fd=1751,opaque=serial0-log \
+-chardev pty,id=charserial0,logfile=/dev/fdset/1,logappend=on \
 -device pci-serial,chardev=charserial0,id=serial0,bus=pci.2,addr=0x1 \
 -msg timestamp=on
diff --git a/tests/qemuxml2argvdata/name-escape.x86_64-2.11.0.args b/tests/qemuxml2argvdata/name-escape.x86_64-2.11.0.args
index 6d4c5bff6e..7f9677abb6 100644
--- a/tests/qemuxml2argvdata/name-escape.x86_64-2.11.0.args
+++ b/tests/qemuxml2argvdata/name-escape.x86_64-2.11.0.args
@@ -33,8 +33,8 @@ QEMU_AUDIO_DRV=spice \
 -device ccid-card-emulated,backend=certificates,cert1=cert1,,foo,cert2=cert2,cert3=cert3,db=/etc/pki/nssdb,,foo,id=smartcard0,bus=ccid0.0 \
 -chardev tty,id=charserial0,path=/dev/ttyS2,,foo \
 -device isa-serial,chardev=charserial0,id=serial0,index=1 \
--add-fd set=0,fd=1750 \
--chardev file,id=charserial1,path=/dev/fdset/0,append=on \
+-add-fd set=1,fd=1750,opaque=serial1-source \
+-chardev file,id=charserial1,path=/dev/fdset/1,append=on \
 -device isa-serial,chardev=charserial1,id=serial1,index=0 \
 -chardev pipe,id=charchannel0,path=/tmp/guestfwd,,foo \
 -netdev user,guestfwd=tcp:10.0.2.1:4600-chardev:charchannel0,id=channel0 \
diff --git a/tests/qemuxml2argvdata/name-escape.x86_64-latest.args b/tests/qemuxml2argvdata/name-escape.x86_64-latest.args
index 0b3247b6bd..665a016a40 100644
--- a/tests/qemuxml2argvdata/name-escape.x86_64-latest.args
+++ b/tests/qemuxml2argvdata/name-escape.x86_64-latest.args
@@ -35,8 +35,8 @@ XDG_CONFIG_HOME=/tmp/lib/domain--1-foo=1,bar=2/.config \
 -device '{"driver":"ccid-card-emulated","backend":"certificates","cert1":"cert1,foo","cert2":"cert2","cert3":"cert3","db":"/etc/pki/nssdb,foo","id":"smartcard0","bus":"ccid0.0"}' \
 -chardev tty,id=charserial0,path=/dev/ttyS2,,foo \
 -device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":1}' \
--add-fd set=0,fd=1750 \
--chardev file,id=charserial1,path=/dev/fdset/0,append=on \
+-add-fd set=1,fd=1750,opaque=serial1-source \
+-chardev file,id=charserial1,path=/dev/fdset/1,append=on \
 -device '{"driver":"isa-serial","chardev":"charserial1","id":"serial1","index":0}' \
 -chardev pipe,id=charchannel0,path=/tmp/guestfwd,,foo \
 -netdev user,guestfwd=tcp:10.0.2.1:4600-chardev:charchannel0,id=channel0 \
diff --git a/tests/qemuxml2argvdata/serial-file-chardev.args b/tests/qemuxml2argvdata/serial-file-chardev.args
index 7df5c2a115..e4dee0033c 100644
--- a/tests/qemuxml2argvdata/serial-file-chardev.args
+++ b/tests/qemuxml2argvdata/serial-file-chardev.args
@@ -29,8 +29,8 @@ QEMU_AUDIO_DRV=none \
 -usb \
 -drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
 -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 \
--add-fd set=0,fd=1750 \
--chardev file,id=charserial0,path=/dev/fdset/0,append=on \
+-add-fd set=1,fd=1750,opaque=serial0-source \
+-chardev file,id=charserial0,path=/dev/fdset/1,append=on \
 -device isa-serial,chardev=charserial0,id=serial0,index=0 \
 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
 -msg timestamp=on
diff --git a/tests/qemuxml2argvdata/serial-file-chardev.x86_64-latest.args b/tests/qemuxml2argvdata/serial-file-chardev.x86_64-latest.args
index 6a28170503..568a1aaf76 100644
--- a/tests/qemuxml2argvdata/serial-file-chardev.x86_64-latest.args
+++ b/tests/qemuxml2argvdata/serial-file-chardev.x86_64-latest.args
@@ -31,8 +31,8 @@ XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
 -blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
 -blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \
 -device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}' \
--add-fd set=0,fd=1750 \
--chardev file,id=charserial0,path=/dev/fdset/0,append=on \
+-add-fd set=1,fd=1750,opaque=serial0-source \
+-chardev file,id=charserial0,path=/dev/fdset/1,append=on \
 -device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0}' \
 -audiodev '{"id":"audio1","driver":"none"}' \
 -device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \
diff --git a/tests/qemuxml2argvdata/serial-file-log.args b/tests/qemuxml2argvdata/serial-file-log.args
index 72d7c49298..1d237ca7c7 100644
--- a/tests/qemuxml2argvdata/serial-file-log.args
+++ b/tests/qemuxml2argvdata/serial-file-log.args
@@ -29,8 +29,8 @@ QEMU_AUDIO_DRV=none \
 -usb \
 -drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
 -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 \
--add-fd set=0,fd=1750 \
--add-fd set=1,fd=1751 \
--chardev file,id=charserial0,path=/dev/fdset/0,append=on,logfile=/dev/fdset/1,logappend=on \
+-add-fd set=1,fd=1750,opaque=serial0-source \
+-add-fd set=2,fd=1751,opaque=serial0-log \
+-chardev file,id=charserial0,path=/dev/fdset/1,append=on,logfile=/dev/fdset/2,logappend=on \
 -device isa-serial,chardev=charserial0,id=serial0,index=0 \
 -msg timestamp=on
diff --git a/tests/qemuxml2argvdata/serial-file-log.x86_64-latest.args b/tests/qemuxml2argvdata/serial-file-log.x86_64-latest.args
index c12b4b3a60..de47bad812 100644
--- a/tests/qemuxml2argvdata/serial-file-log.x86_64-latest.args
+++ b/tests/qemuxml2argvdata/serial-file-log.x86_64-latest.args
@@ -31,9 +31,9 @@ XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
 -blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}' \
 -blockdev '{"node-name":"libvirt-1-format","read-only":false,"driver":"raw","file":"libvirt-1-storage"}' \
 -device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}' \
--add-fd set=0,fd=1750 \
--add-fd set=1,fd=1751 \
--chardev file,id=charserial0,path=/dev/fdset/0,append=on,logfile=/dev/fdset/1,logappend=on \
+-add-fd set=1,fd=1750,opaque=serial0-source \
+-add-fd set=2,fd=1751,opaque=serial0-log \
+-chardev file,id=charserial0,path=/dev/fdset/1,append=on,logfile=/dev/fdset/2,logappend=on \
 -device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0}' \
 -audiodev '{"id":"audio1","driver":"none"}' \
 -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
diff --git a/tests/qemuxml2argvdata/serial-many-chardev.args b/tests/qemuxml2argvdata/serial-many-chardev.args
index 5e80348d11..95a828e606 100644
--- a/tests/qemuxml2argvdata/serial-many-chardev.args
+++ b/tests/qemuxml2argvdata/serial-many-chardev.args
@@ -31,8 +31,8 @@ QEMU_AUDIO_DRV=none \
 -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 \
 -chardev pty,id=charserial0 \
 -device isa-serial,chardev=charserial0,id=serial0,index=0 \
--add-fd set=0,fd=1750 \
--chardev file,id=charserial1,path=/dev/fdset/0,append=on \
+-add-fd set=1,fd=1750,opaque=serial1-source \
+-chardev file,id=charserial1,path=/dev/fdset/1,append=on \
 -device isa-serial,chardev=charserial1,id=serial1,index=1 \
 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
 -msg timestamp=on
diff --git a/tests/qemuxml2argvdata/serial-many-chardev.x86_64-latest.args b/tests/qemuxml2argvdata/serial-many-chardev.x86_64-latest.args
index cbdcc82052..0e5ebaf9e9 100644
--- a/tests/qemuxml2argvdata/serial-many-chardev.x86_64-latest.args
+++ b/tests/qemuxml2argvdata/serial-many-chardev.x86_64-latest.args
@@ -33,8 +33,8 @@ XDG_CONFIG_HOME=/tmp/lib/domain--1-QEMUGuest1/.config \
 -device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-format","id":"ide0-0-0","bootindex":1}' \
 -chardev pty,id=charserial0 \
 -device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0}' \
--add-fd set=0,fd=1750 \
--chardev file,id=charserial1,path=/dev/fdset/0,append=on \
+-add-fd set=1,fd=1750,opaque=serial1-source \
+-chardev file,id=charserial1,path=/dev/fdset/1,append=on \
 -device '{"driver":"isa-serial","chardev":"charserial1","id":"serial1","index":1}' \
 -audiodev '{"id":"audio1","driver":"none"}' \
 -device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x2"}' \
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index b2d6606d6e..d4e518e3a1 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -383,10 +383,17 @@ testPrepareHostBackendChardevOne(virDomainDeviceDef *dev,
                                  virDomainChrSourceDef *chardev,
                                  void *opaque)
 {
-    virQEMUCaps *qemuCaps = opaque;
+    virDomainObj *vm = opaque;
+    qemuDomainObjPrivate *priv = vm->privateData;
     qemuDomainChrSourcePrivate *charpriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(chardev);
+    int fakesourcefd = -1;
+    const char *devalias = NULL;
+    bool usefdset = true;

     if (dev) {
+        virDomainDeviceInfo *info = virDomainDeviceGetInfo(dev);
+        devalias = info->alias;
+
         /* vhost-user disk doesn't use FD passing */
         if (dev->type == VIR_DOMAIN_DEVICE_DISK)
             return 0;
@@ -400,6 +407,8 @@ testPrepareHostBackendChardevOne(virDomainDeviceDef *dev,
         /* TPMs FD passing setup is special and handled separately */
         if (dev->type == VIR_DOMAIN_DEVICE_TPM)
             return 0;
+    } else {
+        devalias = "monitor";
     }

     switch ((virDomainChrType) chardev->type) {
@@ -416,20 +425,15 @@ testPrepareHostBackendChardevOne(virDomainDeviceDef *dev,
         break;

     case VIR_DOMAIN_CHR_TYPE_FILE:
-        if (fcntl(1750, F_GETFD) != -1)
-            abort();
-        charpriv->fd = 1750;
+        fakesourcefd = 1750;
         break;

     case VIR_DOMAIN_CHR_TYPE_UNIX:
         if (chardev->data.nix.listen &&
-            virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS_COMMANDLINE)) {
+            virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS_COMMANDLINE))
+            fakesourcefd = 1729;

-            if (fcntl(1729, F_GETFD) != -1)
-                abort();
-
-            charpriv->fd = 1729;
-        }
+        usefdset = false;
         break;

     case VIR_DOMAIN_CHR_TYPE_NMDM:
@@ -437,10 +441,26 @@ testPrepareHostBackendChardevOne(virDomainDeviceDef *dev,
         break;
     }

+    if (fakesourcefd != -1) {
+        if (fcntl(fakesourcefd, F_GETFD) != -1)
+            abort();
+
+        charpriv->sourcefd = qemuFDPassNew(devalias, priv, usefdset);
+
+        if (qemuFDPassAddFD(charpriv->sourcefd, &fakesourcefd, "-source") < 0)
+            return -1;
+    }
+
     if (chardev->logfile) {
-        if (fcntl(1751, F_GETFD) != -1)
+        int fd = 1751;
+
+        if (fcntl(fd, F_GETFD) != -1)
             abort();
-        charpriv->logfd = 1751;
+
+        charpriv->logfd = qemuFDPassNew(devalias, priv, true);
+
+        if (qemuFDPassAddFD(charpriv->logfd, &fd, "-log") < 0)
+            return -1;
     }

     return 0;
@@ -464,17 +484,11 @@ testCompareXMLToArgvCreateArgs(virQEMUDriver *drv,

     if (qemuDomainDeviceBackendChardevForeach(vm->def,
                                               testPrepareHostBackendChardevOne,
-                                              info->qemuCaps) < 0)
+                                              vm) < 0)
         return NULL;

-    if (virQEMUCapsGet(info->qemuCaps, QEMU_CAPS_CHARDEV_FD_PASS_COMMANDLINE)) {
-        qemuDomainChrSourcePrivate *monpriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(priv->monConfig);
-
-        if (fcntl(1729, F_GETFD) != -1)
-            abort();
-
-        monpriv->fd = 1729;
-    }
+    if (testPrepareHostBackendChardevOne(NULL, priv->monConfig, vm) < 0)
+        return NULL;

     for (i = 0; i < vm->def->ndisks; i++) {
         virDomainDiskDef *disk = vm->def->disks[i];
-- 
2.34.1




More information about the libvir-list mailing list