}
-/**
- * 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
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;
}
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);
path = dev->logfile;
append = dev->logappend;
- if (chrSourcePriv->logFdset) {
- path = chrSourcePriv->logFdset;
+ if (chrSourcePriv->logfd) {
+ path = qemuFDPassGetPath(chrSourcePriv->logfd);
append = VIR_TRISTATE_SWITCH_ON;
}
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:
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;
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 = qemuFDPassNewDirect(video->info.alias, priv);
+
+ if (qemuFDPassAddFD(chrsrcpriv->sourcefd,
+ &videopriv->vhost_user_fd,
+ "-vhost-user") < 0)
+ return -1;
if (qemuBuildChardevCommand(cmd, chrsrc, chrAlias, priv->qemuCaps) < 0)
return -1;
if (!(priv = virObjectNew(qemuDomainChrSourcePrivateClass)))
return NULL;
- priv->fd = -1;
- priv->logfd = -1;
-
- priv->passedFD = -1;
-
return (virObject *) priv;
}
{
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);
#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"
* 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 */
};
virLogManager *logManager;
virQEMUDriverConfig *cfg;
virDomainDef *def;
+ const char *fdprefix;
};
{
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;
/* 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) {
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);
+
+ 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)
+ charpriv->sourcefd = qemuFDPassNewDirect(devalias, data->priv);
+
+ if (qemuFDPassAddFD(charpriv->sourcefd, &sourcefd, "-source") < 0)
return -1;
}
break;
}
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);
+
+ if (qemuFDPassAddFD(charpriv->logfd, &logfd, "-log") < 0)
+ return -1;
}
return 0;
&data) < 0)
return -1;
+ data.fdprefix = "monitor";
+
if (qemuProcessPrepareHostBackendChardevOne(NULL, priv->monConfig, &data) < 0)
return -1;
-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 \
+-add-fd set=0,fd=1751,opaque=serial0-log \
-chardev pty,id=charserial0,logfile=/dev/fdset/0,logappend=on \
-device pci-serial,chardev=charserial0,id=serial0,bus=pci.2,addr=0x1 \
-msg timestamp=on
-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 \
+-add-fd set=0,fd=1750,opaque=serial1-source \
-chardev file,id=charserial1,path=/dev/fdset/0,append=on \
-device isa-serial,chardev=charserial1,id=serial1,index=0 \
-chardev pipe,id=charchannel0,path=/tmp/guestfwd,,foo \
-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 \
+-add-fd set=0,fd=1750,opaque=serial1-source \
-chardev file,id=charserial1,path=/dev/fdset/0,append=on \
-device '{"driver":"isa-serial","chardev":"charserial1","id":"serial1","index":0}' \
-chardev pipe,id=charchannel0,path=/tmp/guestfwd,,foo \
-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=0,fd=1750,opaque=serial0-source \
-chardev file,id=charserial0,path=/dev/fdset/0,append=on \
-device isa-serial,chardev=charserial0,id=serial0,index=0 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
-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=0,fd=1750,opaque=serial0-source \
-chardev file,id=charserial0,path=/dev/fdset/0,append=on \
-device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0}' \
-audiodev '{"id":"audio1","driver":"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 \
+-add-fd set=0,fd=1750,opaque=serial0-source \
+-add-fd set=1,fd=1751,opaque=serial0-log \
-chardev file,id=charserial0,path=/dev/fdset/0,append=on,logfile=/dev/fdset/1,logappend=on \
-device isa-serial,chardev=charserial0,id=serial0,index=0 \
-msg timestamp=on
-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 \
+-add-fd set=0,fd=1750,opaque=serial0-source \
+-add-fd set=1,fd=1751,opaque=serial0-log \
-chardev file,id=charserial0,path=/dev/fdset/0,append=on,logfile=/dev/fdset/1,logappend=on \
-device '{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0}' \
-audiodev '{"id":"audio1","driver":"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 \
+-add-fd set=0,fd=1750,opaque=serial1-source \
-chardev file,id=charserial1,path=/dev/fdset/0,append=on \
-device isa-serial,chardev=charserial1,id=serial1,index=1 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
-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 \
+-add-fd set=0,fd=1750,opaque=serial1-source \
-chardev file,id=charserial1,path=/dev/fdset/0,append=on \
-device '{"driver":"isa-serial","chardev":"charserial1","id":"serial1","index":1}' \
-audiodev '{"id":"audio1","driver":"none"}' \
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;
/* 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) {
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:
break;
}
+ if (fakesourcefd != -1) {
+ if (fcntl(fakesourcefd, F_GETFD) != -1)
+ abort();
+
+ if (usefdset)
+ charpriv->sourcefd = qemuFDPassNew(devalias, priv);
+ else
+ charpriv->sourcefd = qemuFDPassNewDirect(devalias, priv);
+
+ 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);
+
+ if (qemuFDPassAddFD(charpriv->logfd, &fd, "-log") < 0)
+ return -1;
}
return 0;
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];