]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
qemu: domain: Add common function to perform memory hotplug checks
authorPeter Krempa <pkrempa@redhat.com>
Thu, 8 Oct 2015 04:06:15 +0000 (06:06 +0200)
committerPeter Krempa <pkrempa@redhat.com>
Wed, 18 Nov 2015 09:32:18 +0000 (10:32 +0100)
Add a function that will aggregate various checks related to memory
hotplug so that they aren't scattered accross various parts of the
code.

src/qemu/qemu_command.c
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_hotplug.c

index c0b361b771d53d686fde2f8703028ed54579bb9a..5dbe6509647ff66b051f68c728c064d05c483e2f 100644 (file)
@@ -9326,26 +9326,12 @@ qemuBuildCommandLine(virConnectPtr conn,
         qemuDomainAlignMemorySizes(def) < 0)
         goto error;
 
+    if (qemuDomainDefValidateMemoryHotplug(def, qemuCaps, NULL) < 0)
+        goto error;
+
     virCommandAddArg(cmd, "-m");
 
     if (virDomainDefHasMemoryHotplug(def)) {
-        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PC_DIMM)) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("memory hotplug isn't supported by this QEMU binary"));
-            goto error;
-        }
-
-        /* due to guest support, qemu would silently enable NUMA with one node
-         * once the memory hotplug backend is enabled. To avoid possible
-         * confusion we will enforce user originated numa configuration along
-         * with memory hotplug. */
-        if (virDomainNumaGetNodeCount(def->numa) == 0) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                           _("At least one numa node has to be configured when "
-                             "enabling memory hotplug"));
-            goto error;
-        }
-
         /* Use the 'k' suffix to let qemu handle the units */
         virCommandAddArgFormat(cmd, "size=%lluk,slots=%u,maxmem=%lluk",
                                virDomainDefGetMemoryInitial(def),
@@ -9408,12 +9394,6 @@ qemuBuildCommandLine(virConnectPtr conn,
     /* memory hotplug requires NUMA to be enabled - we already checked
      * that memory devices are present only when NUMA is */
 
-    if (def->nmems > def->mem.memory_slots) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                       _("memory device count '%zu' exceeds slots count '%u'"),
-                       def->nmems, def->mem.memory_slots);
-        goto error;
-    }
 
     for (i = 0; i < def->nmems; i++) {
         char *backStr;
index 3d2b7a0c9682270237d12ea0491a6a0fc97d4885..cb4cd0b9dd78283086fd0797d58149c886387317 100644 (file)
@@ -3558,6 +3558,84 @@ qemuDomainMachineIsS390CCW(const virDomainDef *def)
 }
 
 
+/**
+ * qemuDomainDefValidateMemoryHotplug:
+ * @def: domain definition
+ * @qemuCaps: qemu capabilities object
+ * @mem: definition of memory device that is to be added to @def with hotplug,
+ *       NULL in case of regular VM startup
+ *
+ * Validates that the domain definition and memory modules have valid
+ * configuration and are possibly able to accept @mem via hotplug if it's
+ * non-NULL.
+ *
+ * Returns 0 on success; -1 and a libvirt error on error.
+ */
+int
+qemuDomainDefValidateMemoryHotplug(const virDomainDef *def,
+                                   virQEMUCapsPtr qemuCaps,
+                                   const virDomainMemoryDef *mem)
+{
+    unsigned int nmems = def->nmems;
+    unsigned long long hotplugSpace;
+    unsigned long long hotplugMemory = 0;
+    size_t i;
+
+    hotplugSpace = def->mem.max_memory - virDomainDefGetMemoryInitial(def);
+
+    if (mem) {
+        nmems++;
+        hotplugMemory = mem->size;
+    }
+
+    if (!virDomainDefHasMemoryHotplug(def)) {
+        if (nmems) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("cannot use/hotplug a memory device when domain "
+                             "'maxMemory' is not defined"));
+            return -1;
+        }
+
+        return 0;
+    }
+
+    if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_PC_DIMM)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("memory hotplug isn't supported by this QEMU binary"));
+        return -1;
+    }
+
+    /* due to guest support, qemu would silently enable NUMA with one node
+     * once the memory hotplug backend is enabled. To avoid possible
+     * confusion we will enforce user originated numa configuration along
+     * with memory hotplug. */
+    if (virDomainNumaGetNodeCount(def->numa) == 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("At least one numa node has to be configured when "
+                         "enabling memory hotplug"));
+        return -1;
+    }
+
+    if (nmems > def->mem.memory_slots) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("memory device count '%u' exceeds slots count '%u'"),
+                       nmems, def->mem.memory_slots);
+        return -1;
+    }
+
+    for (i = 0; i < def->nmems; i++)
+        hotplugMemory += def->mems[i]->size;
+
+    if (hotplugMemory > hotplugSpace) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("memory device total size exceeds hotplug space"));
+        return -1;
+    }
+
+    return 0;
+}
+
+
 /**
  * qemuDomainUpdateCurrentMemorySize:
  *
index 4be998c27d4ba392c3010a30c8969f2d8fb024f4..90b482d424c3b42970f0c16189837ef6fe4022f0 100644 (file)
@@ -485,4 +485,8 @@ int qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver,
 unsigned long long qemuDomainGetMlockLimitBytes(virDomainDefPtr def);
 bool qemuDomainRequiresMlock(virDomainDefPtr def);
 
+int qemuDomainDefValidateMemoryHotplug(const virDomainDef *def,
+                                       virQEMUCapsPtr qemuCaps,
+                                       const virDomainMemoryDef *mem);
+
 #endif /* __QEMU_DOMAIN_H__ */
index 9a8bd9ee35f3bf28d9d3bcbd97daad069b35ba67..ccef8d5656d2f0b637b4168115422361ea781c64 100644 (file)
@@ -1767,11 +1767,10 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
     int id;
     int ret = -1;
 
-    if (vm->def->nmems == vm->def->mem.memory_slots) {
-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
-                       _("no free memory device slot available"));
+    qemuDomainMemoryDeviceAlignSize(vm->def, mem);
+
+    if (qemuDomainDefValidateMemoryHotplug(vm->def, priv->qemuCaps, mem) < 0)
         goto cleanup;
-    }
 
     if (virAsprintf(&mem->info.alias, "dimm%zu", vm->def->nmems) < 0)
         goto cleanup;
@@ -1785,8 +1784,6 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
     if (!(devstr = qemuBuildMemoryDeviceStr(mem, vm->def, priv->qemuCaps)))
         goto cleanup;
 
-    qemuDomainMemoryDeviceAlignSize(vm->def, mem);
-
     if (qemuBuildMemoryBackendStr(mem->size, mem->pagesize,
                                   mem->targetNode, mem->sourceNodes, NULL,
                                   vm->def, priv->qemuCaps, cfg,