qemu: Fix race condition when detaching a device

If QEMU replies to device_del command with "DeviceNotFound"
error, then libvirt doesn't clean the device from the live
configuration.

This is because qemuMonitorDelDevice() returns -2 to
qemuDomainDeleteDevice() and instead of calling
qemuDomainRemoveDevice() the qemuDomainDetachDeviceLive() jumps
right onto cleanup label.

Resolves: https://gitlab.com/libvirt/libvirt/-/issues/359
Signed-off-by: Pierre LIBEAU <pierre.libeau@corp.ovh.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Pierre LIBEAU 2022-08-31 14:22:51 +02:00 committed by Michal Privoznik
parent c4dcec1318
commit f30843142a

View File

@ -93,6 +93,8 @@ qemuDomainResetDeviceRemoval(virDomainObj *vm);
*
* Returns: 0 on success,
* -1 otherwise.
* -2 device does not exist in qemu, but it still
* exists in libvirt
*/
static int
qemuDomainDeleteDevice(virDomainObj *vm,
@ -124,7 +126,6 @@ qemuDomainDeleteDevice(virDomainObj *vm,
* domain XML is queried right after detach API the
* device would still be there. */
VIR_DEBUG("Detaching of device %s failed and no event arrived", alias);
rc = 0;
}
}
@ -5864,6 +5865,7 @@ qemuDomainDetachDeviceLive(virDomainObj *vm,
virDomainDeviceDef detach = { .type = match->type };
virDomainDeviceInfo *info = NULL;
int ret = -1;
int rc;
switch ((virDomainDeviceType)match->type) {
/*
@ -6053,7 +6055,10 @@ qemuDomainDetachDeviceLive(virDomainObj *vm,
if (!async)
qemuDomainMarkDeviceForRemoval(vm, info);
if (qemuDomainDeleteDevice(vm, info->alias) < 0) {
rc = qemuDomainDeleteDevice(vm, info->alias);
if (rc < 0) {
if (rc == -2)
ret = qemuDomainRemoveDevice(driver, vm, &detach);
if (virDomainObjIsActive(vm))
qemuDomainRemoveAuditDevice(vm, &detach, false);
goto cleanup;