qemu_hotplug: Close FDs in QEMU on failed chardev hotplug

When hotplugging a chardev, Libvirt opens corresponding
file/binds to a socket/does whatever necessary to obtain an FD
that is later passed to QEMU. However, if something fails after
the FDs were transferred to QEMU and before chardev is actually
added via monitor, these FDs are never closed in QEMU. This is
rather suboptimal.

Fixes: 15bdced9b3
Fixes: ad81aa8ad0
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Kristina Hanicova <khanicov@redhat.com>
This commit is contained in:
Michal Privoznik 2022-07-18 16:29:07 +02:00
parent 7437f35642
commit 14f42129fc

View File

@ -2132,17 +2132,6 @@ qemuDomainAttachChrDevice(virQEMUDriver *driver,
if (qemuProcessPrepareHostBackendChardevHotplug(vm, dev) < 0)
goto cleanup;
if (charpriv->sourcefd || charpriv->logfd || charpriv->directfd) {
qemuDomainObjEnterMonitor(driver, vm);
if (qemuFDPassTransferMonitor(charpriv->sourcefd, priv->mon) < 0 ||
qemuFDPassTransferMonitor(charpriv->logfd, priv->mon) < 0 ||
qemuFDPassDirectTransferMonitor(charpriv->directfd, priv->mon) < 0)
goto exit_monitor;
qemuDomainObjExitMonitor(vm);
}
if (guestfwd) {
if (!(netdevprops = qemuBuildChannelGuestfwdNetdevProps(chr)))
goto cleanup;
@ -2164,6 +2153,11 @@ qemuDomainAttachChrDevice(virQEMUDriver *driver,
qemuDomainObjEnterMonitor(driver, vm);
if (qemuFDPassTransferMonitor(charpriv->sourcefd, priv->mon) < 0 ||
qemuFDPassTransferMonitor(charpriv->logfd, priv->mon) < 0 ||
qemuFDPassDirectTransferMonitor(charpriv->directfd, priv->mon) < 0)
goto exit_monitor;
if (qemuHotplugChardevAttach(priv->mon, charAlias, chr->source) < 0)
goto exit_monitor;
chardevAttached = true;
@ -2209,6 +2203,7 @@ qemuDomainAttachChrDevice(virQEMUDriver *driver,
qemuMonitorDetachCharDev(priv->mon, charAlias);
qemuFDPassTransferMonitorRollback(charpriv->sourcefd, priv->mon);
qemuFDPassTransferMonitorRollback(charpriv->logfd, priv->mon);
qemuFDPassDirectTransferMonitorRollback(charpriv->directfd, priv->mon);
qemuDomainObjExitMonitor(vm);
virErrorRestore(&orig_err);