]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: Release <memory/> device address on failed hotplug
authorMichal Privoznik <mprivozn@redhat.com>
Mon, 8 Feb 2021 14:21:16 +0000 (15:21 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Mon, 8 Feb 2021 19:05:08 +0000 (20:05 +0100)
A few commits back I've introduced new 'virtio-pmem' <memory/>
device. Since it's virtio it goes onto PCI bus. Therefore, on
hotplug new PCI address is generated (or provided one is
reserved). However, if hotplug fails (for whatever reason) the
address needs to be released. This is different to 'dimm' type of
address because for that type we don't keep a map of used slots
rather generate one on each address assign request. The map is
then thrown away. But for PCI addresses we keep internal state
and thus has to keep it updated. Therefore, this new
qemuDomainReleaseMemoryDeviceSlot() function is NOP for those
models which use 'dimm' address type ('dimm' and 'nvdimm').

While I'm at it, let's release the address in case of hot unplug.
Not that is supported (any such attempt fails with the following
error:

  "virtio based memory devices cannot be unplugged"

But if QEMU ever implements hot unplug then we don't have to
remember to fix our code.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
src/qemu/qemu_domain_address.c
src/qemu/qemu_domain_address.h
src/qemu/qemu_hotplug.c

index 1171dc5b14766aaff96a1c5f5de43e2216ddb3e2..68dbf9e95b6afd723dcb4fd412bd2287867068b3 100644 (file)
@@ -3122,6 +3122,29 @@ qemuDomainAssignMemoryDeviceSlot(virQEMUDriverPtr driver,
 }
 
 
+void
+qemuDomainReleaseMemoryDeviceSlot(virDomainObjPtr vm,
+                                  virDomainMemoryDefPtr mem)
+{
+    switch (mem->model) {
+    case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+    case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
+        /* We don't need to release anything. Slot map is not
+         * kept around. It's constructed every time when
+         * assigning new slot. */
+        break;
+
+    case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
+        qemuDomainReleaseDeviceAddress(vm, &mem->info);
+        break;
+
+    case VIR_DOMAIN_MEMORY_MODEL_NONE:
+    case VIR_DOMAIN_MEMORY_MODEL_LAST:
+        break;
+    }
+}
+
+
 static int
 qemuDomainAssignMemorySlots(virDomainDefPtr def)
 {
index 20a46160d5df6a07bfdac35c2f7da1f77da5a407..bfd56e163eab7510f375b337bb564a32938a6ffb 100644 (file)
@@ -60,6 +60,9 @@ int qemuDomainAssignMemoryDeviceSlot(virQEMUDriverPtr driver,
                                      virDomainObjPtr vm,
                                      virDomainMemoryDefPtr mem);
 
+void qemuDomainReleaseMemoryDeviceSlot(virDomainObjPtr vm,
+                                       virDomainMemoryDefPtr mem);
+
 int qemuDomainEnsureVirtioAddress(bool *releaseAddr,
                                   virDomainObjPtr vm,
                                   virDomainDeviceDefPtr dev,
index 94c3df636899e654cbd775c32d16c147c638c34a..dc2b46057c8de47dbdb9bb88c287f767f5a061ac 100644 (file)
@@ -2400,6 +2400,7 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
     g_autofree char *devstr = NULL;
     g_autofree char *objalias = NULL;
     bool objAdded = false;
+    bool releaseaddr = false;
     bool teardownlabel = false;
     bool teardowncgroup = false;
     bool teardowndevice = false;
@@ -2416,6 +2417,7 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
 
     if (qemuDomainAssignMemoryDeviceSlot(driver, vm, mem) < 0)
         goto cleanup;
+    releaseaddr = true;
 
     /* in cases where we are using a VM with aliases generated according to the
      * index of the memory device we need to keep continue using that scheme */
@@ -2492,6 +2494,8 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
         if (teardowndevice &&
             qemuDomainNamespaceTeardownMemory(vm, mem) <  0)
             VIR_WARN("Unable to remove memory device from /dev");
+        if (releaseaddr)
+            qemuDomainReleaseMemoryDeviceSlot(vm, mem);
     }
 
     virJSONValueFree(props);
@@ -4457,6 +4461,8 @@ qemuDomainRemoveMemoryDevice(virQEMUDriverPtr driver,
     if (qemuProcessDestroyMemoryBackingPath(driver, vm, mem) < 0)
         VIR_WARN("Unable to destroy memory backing path");
 
+    qemuDomainReleaseMemoryDeviceSlot(vm, mem);
+
     virDomainMemoryDefFree(mem);
 
     /* fix the balloon size */