]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemuDomainRemoveChrDevice: Deal with qemuDomainChrRemove() failure
authorMichal Privoznik <mprivozn@redhat.com>
Wed, 12 Apr 2023 08:22:42 +0000 (10:22 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 18 Apr 2023 14:02:35 +0000 (16:02 +0200)
When cleaning up after removed device, qemuDomainChrRemove() is
called. But this may fail, in which case we successfully ignore
the failure and virDomainChrDefFree() the device anyway. While it
decreases our memory consumption, it's a bit too far, especially
if the next step is 'virsh dumpxml'. Then our memory consumption
decreases all the way down to zero as we crash.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_hotplug.c

index a6407f074b224ca6e271513a857f79ac0c57975a..d9a102191fd0369c403fc61474089f8858de0052 100644 (file)
@@ -4695,6 +4695,7 @@ qemuDomainRemoveChrDevice(virQEMUDriver *driver,
     virObjectEvent *event;
     g_autofree char *charAlias = NULL;
     qemuDomainObjPrivate *priv = vm->privateData;
+    virDomainChrDef *chrRemoved = NULL;
     int rc = 0;
 
     VIR_DEBUG("Removing character device %s from domain %p %s",
@@ -4728,17 +4729,24 @@ qemuDomainRemoveChrDevice(virQEMUDriver *driver,
     if (qemuDomainNamespaceTeardownChardev(vm, chr) < 0)
         VIR_WARN("Unable to remove chr device from /dev");
 
-    qemuDomainReleaseDeviceAddress(vm, &chr->info);
-    qemuDomainChrRemove(vm->def, chr);
+    if (!(chrRemoved = qemuDomainChrRemove(vm->def, chr))) {
+        /* At this point, we only have bad options. The device
+         * was successfully removed from QEMU, denied in CGropus,
+         * etc. and yet, we failed to remove it from domain
+         * definition. */
+        VIR_WARN("Unable to remove chr device from domain definition");
+    } else {
+        qemuDomainReleaseDeviceAddress(vm, &chrRemoved->info);
 
-    /* The caller does not emit the event, so we must do it here. Note
-     * that the event should be reported only after all backend
-     * teardown is completed.
-     */
-    event = virDomainEventDeviceRemovedNewFromObj(vm, chr->info.alias);
-    virObjectEventStateQueue(driver->domainEventState, event);
+        /* The caller does not emit the event, so we must do it here. Note
+         * that the event should be reported only after all backend
+         * teardown is completed.
+         */
+        event = virDomainEventDeviceRemovedNewFromObj(vm, chrRemoved->info.alias);
+        virObjectEventStateQueue(driver->domainEventState, event);
 
-    virDomainChrDefFree(chr);
+        virDomainChrDefFree(chrRemoved);
+    }
     return 0;
 }