The VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event is sent after qemu has responded to a device_del command with a DEVICE_DELETED event. Before queuing the event, *some* of the final teardown of the device's trappings in libvirt is done, but not *all* of it. As a result, an application may receive and process the DEVICE_REMOVED event before libvirt has really finished with it. Usually this doesn't cause a problem, but it can - in the case of the bug report referenced below, vdsm is assigning a PCI device to a guest with managed='no', using livirt's virNodeDeviceDetachFlags() and virNodeDeviceReAttach() APIs. Immediately after receiving a DEVICE_REMOVED event from libvirt signalling that the device had been successfully unplugged, vdsm would cal virNodeDeviceReAttach() to unbind the device from vfio-pci and rebind it to the host driverm but because the event was received before libvirt had completely finished processing the removal, that device was still on the "activeDevs" list, and so virNodeDeviceReAttach() failed. Experimentation with additional debug logs proved that libvirt would always end up dispatching the DEVICE_REMOVED event before it had removed the device from activeDevs (with a *much* greater difference with managed='yes', since in that case the re-binding of the device occurred after queuing the device). Although the case of hostdev devices is the most extreme (since there is so much involved in tearing down the device), *all* device types suffer from the same problem - the DEVICE_REMOVED event is queued very early in the qemuDomainRemove*Device() function for all of them, resulting in a possibility of any application receiving the event before libvirt has really finished with the device. The solution is to save the device's alias (which is the only piece of info from the device object that is needed for the event) at the beginning of processing the device removal, and then queue the event as a final act before returning. Since all of the qemuDomainRemove*Device() functions (except qemuDomainRemoveChrDevice()) are now called exclusively from qemuDomainRemoveDevice() (which selects which of the subordinates to call in a switch statement based on the type of device), the shortest route to a solution is to doing the saving of alias, and later queueing of the event, in the higher level qemuDomainRemoveDevice(), and just completely remove the event-related code from all the subordinate functions. The single exception to this, as mentioned before, is qemuDomainRemoveChrDevice(), which is still called from somewhere other than qemuDomainRemoveDevice() (and has a separate arg used to trigger different behavior when the chr device has targetType == GUESTFWD), so it must keep its original behavior intact, and must be treated differently by qemuDomainRemoveDevice() (similar to the way that qemuDomainDetachDeviceLive() treats chr and lease devices differently from all the others). Resolves: https://bugzilla.redhat.com/1658198 Signed-off-by: Laine Stump <laine@laine.org> ACKed-by: Peter Krempa <pkrempa@redhat.com>
Libvirt API for virtualization
Libvirt provides a portable, long term stable C API for managing the virtualization technologies provided by many operating systems. It includes support for QEMU, KVM, Xen, LXC, bhyve, Virtuozzo, VMware vCenter and ESX, VMware Desktop, Hyper-V, VirtualBox and the POWER Hypervisor.
For some of these hypervisors, it provides a stateful management daemon which runs on the virtualization host allowing access to the API both by non-privileged local users and remote users.
Layered packages provide bindings of the libvirt C API into other languages including Python, Perl, PHP, Go, Java, OCaml, as well as mappings into object systems such as GObject, CIM and SNMP.
Further information about the libvirt project can be found on the website:
License
The libvirt C API is distributed under the terms of GNU Lesser General
Public License, version 2.1 (or later). Some parts of the code that are
not part of the C library may have the more restrictive GNU General
Public License, version 2.1 (or later). See the files COPYING.LESSER
and COPYING
for full license terms & conditions.
Installation
Libvirt uses the GNU Autotools build system, so in general can be built and installed with the usual commands. For example, to build in a manner that is suitable for installing as root, use:
$ ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
$ make
$ sudo make install
While to build & install as an unprivileged user
$ ./configure --prefix=$HOME/usr
$ make
$ make install
The libvirt code relies on a large number of 3rd party libraries. These will
be detected during execution of the configure
script and a summary printed
which lists any missing (optional) dependencies.
Contributing
The libvirt project welcomes contributions in many ways. For most components the best way to contribute is to send patches to the primary development mailing list. Further guidance on this can be found on the website:
https://libvirt.org/contribute.html
Contact
The libvirt project has two primary mailing lists:
- libvirt-users@redhat.com (for user discussions)
- libvir-list@redhat.com (for development only)
Further details on contacting the project are available on the website: