diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9279eaf811..d6876baa34 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6730,8 +6730,7 @@ qemuDomainAttachDeviceLive(virDomainObj *vm, break; case VIR_DOMAIN_DEVICE_CHR: - ret = qemuDomainAttachChrDevice(driver, vm, - dev->data.chr); + ret = qemuDomainAttachChrDevice(driver, vm, dev); if (!ret) { alias = dev->data.chr->info.alias; dev->data.chr = NULL; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 05993aa5d7..c70bc361fd 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -2180,10 +2180,14 @@ qemuDomainAttachChrDeviceAssignAddr(virDomainObj *vm, return 0; } -int qemuDomainAttachChrDevice(virQEMUDriver *driver, - virDomainObj *vm, - virDomainChrDef *chr) + +int +qemuDomainAttachChrDevice(virQEMUDriver *driver, + virDomainObj *vm, + virDomainDeviceDef *dev) { + virDomainChrDef *chr = dev->data.chr; + qemuDomainChrSourcePrivate *charpriv = QEMU_DOMAIN_CHR_SOURCE_PRIVATE(chr->source); int ret = -1; qemuDomainObjPrivate *priv = vm->privateData; virErrorPtr orig_err; @@ -2224,6 +2228,19 @@ int qemuDomainAttachChrDevice(virQEMUDriver *driver, goto cleanup; teardowncgroup = true; + if (qemuProcessPrepareHostBackendChardevHotplug(vm, dev) < 0) + goto cleanup; + + if (charpriv->sourcefd || charpriv->logfd) { + qemuDomainObjEnterMonitor(driver, vm); + + if (qemuFDPassTransferMonitor(charpriv->sourcefd, priv->mon) < 0 || + qemuFDPassTransferMonitor(charpriv->logfd, priv->mon) < 0) + goto exit_monitor; + + qemuDomainObjExitMonitor(driver, vm); + } + if (guestfwd) { if (!(netdevprops = qemuBuildChannelGuestfwdNetdevProps(chr))) goto cleanup; @@ -2286,6 +2303,8 @@ int qemuDomainAttachChrDevice(virQEMUDriver *driver, /* detach associated chardev on error */ if (chardevAttached) qemuMonitorDetachCharDev(priv->mon, charAlias); + qemuFDPassTransferMonitorRollback(charpriv->sourcefd, priv->mon); + qemuFDPassTransferMonitorRollback(charpriv->logfd, priv->mon); qemuDomainObjExitMonitor(driver, vm); virErrorRestore(&orig_err); diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index 244dd5278d..19c07497b5 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -117,7 +117,7 @@ int qemuDomainAttachLease(virQEMUDriver *driver, virDomainLeaseDef *lease); int qemuDomainAttachChrDevice(virQEMUDriver *driver, virDomainObj *vm, - virDomainChrDef *chr); + virDomainDeviceDef *dev); int qemuDomainAttachRNGDevice(virQEMUDriver *driver, virDomainObj *vm, virDomainRNGDef *rng); diff --git a/tests/qemuhotplugmock.c b/tests/qemuhotplugmock.c index 051f2b20dc..e3f0715058 100644 --- a/tests/qemuhotplugmock.c +++ b/tests/qemuhotplugmock.c @@ -21,6 +21,7 @@ #include "qemu/qemu_hotplug.h" #include "qemu/qemu_interface.h" #include "qemu/qemu_process.h" +#include "testutilsqemu.h" #include "conf/domain_conf.h" #include "virdevmapper.h" #include "virutil.h" @@ -96,3 +97,13 @@ qemuInterfaceVDPAConnect(virDomainNetDef *net G_GNUC_UNUSED) /* need a valid fd or sendmsg won't work. Just open /dev/null */ return open("/dev/null", O_RDONLY); } + + +int +qemuProcessPrepareHostBackendChardevHotplug(virDomainObj *vm, + virDomainDeviceDef *dev) +{ + return qemuDomainDeviceBackendChardevForeachOne(dev, + testQemuPrepareHostBackendChardevOne, + vm); +} diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index fe1b227b4e..ce215da099 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -135,7 +135,7 @@ testQemuHotplugAttach(virDomainObj *vm, ret = qemuDomainAttachDeviceDiskLive(&driver, vm, dev); break; case VIR_DOMAIN_DEVICE_CHR: - ret = qemuDomainAttachChrDevice(&driver, vm, dev->data.chr); + ret = qemuDomainAttachChrDevice(&driver, vm, dev); break; case VIR_DOMAIN_DEVICE_SHMEM: ret = qemuDomainAttachShmemDevice(&driver, vm, dev->data.shmem);