提交 118c91b0 编写于 作者: P Peter Krempa

qemu: domain: Add common function to perform memory hotplug checks

Add a function that will aggregate various checks related to memory
hotplug so that they aren't scattered accross various parts of the
code.
上级 a4b10a60
......@@ -9326,26 +9326,12 @@ qemuBuildCommandLine(virConnectPtr conn,
qemuDomainAlignMemorySizes(def) < 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"));
if (qemuDomainDefValidateMemoryHotplug(def, qemuCaps, NULL) < 0)
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;
}
virCommandAddArg(cmd, "-m");
if (virDomainDefHasMemoryHotplug(def)) {
/* 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;
......
......@@ -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:
*
......
......@@ -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__ */
......@@ -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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册