mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
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.
This commit is contained in:
parent
a4b10a60ad
commit
118c91b0d5
@ -9326,26 +9326,12 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
qemuDomainAlignMemorySizes(def) < 0)
|
qemuDomainAlignMemorySizes(def) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (qemuDomainDefValidateMemoryHotplug(def, qemuCaps, NULL) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
virCommandAddArg(cmd, "-m");
|
virCommandAddArg(cmd, "-m");
|
||||||
|
|
||||||
if (virDomainDefHasMemoryHotplug(def)) {
|
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 */
|
/* Use the 'k' suffix to let qemu handle the units */
|
||||||
virCommandAddArgFormat(cmd, "size=%lluk,slots=%u,maxmem=%lluk",
|
virCommandAddArgFormat(cmd, "size=%lluk,slots=%u,maxmem=%lluk",
|
||||||
virDomainDefGetMemoryInitial(def),
|
virDomainDefGetMemoryInitial(def),
|
||||||
@ -9408,12 +9394,6 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
/* memory hotplug requires NUMA to be enabled - we already checked
|
/* memory hotplug requires NUMA to be enabled - we already checked
|
||||||
* that memory devices are present only when NUMA is */
|
* 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++) {
|
for (i = 0; i < def->nmems; i++) {
|
||||||
char *backStr;
|
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:
|
* qemuDomainUpdateCurrentMemorySize:
|
||||||
*
|
*
|
||||||
|
@ -485,4 +485,8 @@ int qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver,
|
|||||||
unsigned long long qemuDomainGetMlockLimitBytes(virDomainDefPtr def);
|
unsigned long long qemuDomainGetMlockLimitBytes(virDomainDefPtr def);
|
||||||
bool qemuDomainRequiresMlock(virDomainDefPtr def);
|
bool qemuDomainRequiresMlock(virDomainDefPtr def);
|
||||||
|
|
||||||
|
int qemuDomainDefValidateMemoryHotplug(const virDomainDef *def,
|
||||||
|
virQEMUCapsPtr qemuCaps,
|
||||||
|
const virDomainMemoryDef *mem);
|
||||||
|
|
||||||
#endif /* __QEMU_DOMAIN_H__ */
|
#endif /* __QEMU_DOMAIN_H__ */
|
||||||
|
@ -1767,11 +1767,10 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
|
|||||||
int id;
|
int id;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (vm->def->nmems == vm->def->mem.memory_slots) {
|
qemuDomainMemoryDeviceAlignSize(vm->def, mem);
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
||||||
_("no free memory device slot available"));
|
if (qemuDomainDefValidateMemoryHotplug(vm->def, priv->qemuCaps, mem) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
|
|
||||||
if (virAsprintf(&mem->info.alias, "dimm%zu", vm->def->nmems) < 0)
|
if (virAsprintf(&mem->info.alias, "dimm%zu", vm->def->nmems) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -1785,8 +1784,6 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
|
|||||||
if (!(devstr = qemuBuildMemoryDeviceStr(mem, vm->def, priv->qemuCaps)))
|
if (!(devstr = qemuBuildMemoryDeviceStr(mem, vm->def, priv->qemuCaps)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
qemuDomainMemoryDeviceAlignSize(vm->def, mem);
|
|
||||||
|
|
||||||
if (qemuBuildMemoryBackendStr(mem->size, mem->pagesize,
|
if (qemuBuildMemoryBackendStr(mem->size, mem->pagesize,
|
||||||
mem->targetNode, mem->sourceNodes, NULL,
|
mem->targetNode, mem->sourceNodes, NULL,
|
||||||
vm->def, priv->qemuCaps, cfg,
|
vm->def, priv->qemuCaps, cfg,
|
||||||
|
Loading…
Reference in New Issue
Block a user