mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 11:22:23 +00:00
qemu: pass numa node binding preferences to qemu
Currently, we only bind the whole QEMU domain to memory nodes specified in nodemask altogether. That, however, doesn't make much sense when one wants to control from where the memory for particular guest nodes should be allocated. QEMU allows us to do that by specifying 'host-nodes' parameter for the 'memory-backend-ram' object, so let's use that. Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
parent
001b9dc1dc
commit
1c19d3e072
@ -150,6 +150,11 @@ VIR_ENUM_IMPL(qemuDomainFSDriver, VIR_DOMAIN_FS_DRIVER_TYPE_LAST,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
VIR_ENUM_DECL(qemuNumaPolicy)
|
||||
VIR_ENUM_IMPL(qemuNumaPolicy, VIR_DOMAIN_NUMATUNE_MEM_LAST,
|
||||
"bind",
|
||||
"preferred",
|
||||
"interleave");
|
||||
|
||||
/**
|
||||
* qemuPhysIfaceConnect:
|
||||
@ -6383,13 +6388,23 @@ qemuBuildNumaArgStr(const virDomainDef *def,
|
||||
size_t i;
|
||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||
char *cpumask = NULL, *tmpmask = NULL, *next = NULL;
|
||||
char *nodemask = NULL;
|
||||
int ret = -1;
|
||||
|
||||
if (virDomainNumatuneHasPerNodeBinding(def->numatune) &&
|
||||
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("Per-node memory binding is not supported "
|
||||
"with this QEMU"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (i = 0; i < def->cpu->ncells; i++) {
|
||||
int cellmem = VIR_DIV_UP(def->cpu->cells[i].mem, 1024);
|
||||
def->cpu->cells[i].mem = cellmem * 1024;
|
||||
|
||||
VIR_FREE(cpumask);
|
||||
VIR_FREE(nodemask);
|
||||
|
||||
if (!(cpumask = virBitmapFormat(def->cpu->cells[i].cpumask)))
|
||||
goto cleanup;
|
||||
@ -6402,6 +6417,43 @@ qemuBuildNumaArgStr(const virDomainDef *def,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM)) {
|
||||
virDomainNumatuneMemMode mode;
|
||||
const char *policy = NULL;
|
||||
|
||||
mode = virDomainNumatuneGetMode(def->numatune, i);
|
||||
policy = qemuNumaPolicyTypeToString(mode);
|
||||
|
||||
virBufferAsprintf(&buf, "memory-backend-ram,size=%dM,id=ram-node%zu",
|
||||
cellmem, i);
|
||||
|
||||
if (virDomainNumatuneMaybeFormatNodeset(def->numatune, NULL,
|
||||
&nodemask, i) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (nodemask) {
|
||||
if (strchr(nodemask, ',') &&
|
||||
!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA)) {
|
||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||
_("disjoint NUMA node ranges are not supported "
|
||||
"with this QEMU"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
for (tmpmask = nodemask; tmpmask; tmpmask = next) {
|
||||
if ((next = strchr(tmpmask, ',')))
|
||||
*(next++) = '\0';
|
||||
virBufferAddLit(&buf, ",host-nodes=");
|
||||
virBufferAdd(&buf, tmpmask, -1);
|
||||
}
|
||||
|
||||
virBufferAsprintf(&buf, ",policy=%s", policy);
|
||||
}
|
||||
|
||||
virCommandAddArg(cmd, "-object");
|
||||
virCommandAddArgBuffer(cmd, &buf);
|
||||
}
|
||||
|
||||
virCommandAddArg(cmd, "-numa");
|
||||
virBufferAsprintf(&buf, "node,nodeid=%zu", i);
|
||||
|
||||
@ -6412,7 +6464,11 @@ qemuBuildNumaArgStr(const virDomainDef *def,
|
||||
virBufferAdd(&buf, tmpmask, -1);
|
||||
}
|
||||
|
||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM)) {
|
||||
virBufferAsprintf(&buf, ",memdev=ram-node%zu", i);
|
||||
} else {
|
||||
virBufferAsprintf(&buf, ",mem=%d", cellmem);
|
||||
}
|
||||
|
||||
virCommandAddArgBuffer(cmd, &buf);
|
||||
}
|
||||
@ -6420,6 +6476,7 @@ qemuBuildNumaArgStr(const virDomainDef *def,
|
||||
|
||||
cleanup:
|
||||
VIR_FREE(cpumask);
|
||||
VIR_FREE(nodemask);
|
||||
virBufferFreeAndReset(&buf);
|
||||
return ret;
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
|
||||
/usr/bin/kvm -S -M pc -m 64 -smp 2 \
|
||||
-object memory-backend-ram,size=32M,id=ram-node0,host-nodes=3,policy=preferred \
|
||||
-numa node,nodeid=0,cpus=0,memdev=ram-node0 \
|
||||
-object memory-backend-ram,size=32M,id=ram-node1 \
|
||||
-numa node,nodeid=1,cpus=1,memdev=ram-node1 \
|
||||
-nographic -monitor unix:/tmp/test-monitor,server,nowait \
|
||||
-no-acpi -boot c -usb -net none -serial none -parallel none
|
11
tests/qemuxml2argvdata/qemuxml2argv-numatune-memnode.args
Normal file
11
tests/qemuxml2argvdata/qemuxml2argv-numatune-memnode.args
Normal file
@ -0,0 +1,11 @@
|
||||
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
|
||||
/usr/bin/kvm -S -M pc -m 24104 -smp 32 \
|
||||
-object memory-backend-ram,size=20M,id=ram-node0,host-nodes=3,policy=preferred \
|
||||
-numa node,nodeid=0,cpus=0,memdev=ram-node0 \
|
||||
-object memory-backend-ram,size=645M,id=ram-node1,host-nodes=0-7,policy=bind \
|
||||
-numa node,nodeid=1,cpus=1-27,cpus=29,memdev=ram-node1 \
|
||||
-object memory-backend-ram,size=23440M,id=ram-node2,\
|
||||
host-nodes=1-2,host-nodes=5,host-nodes=7,policy=bind \
|
||||
-numa node,nodeid=2,cpus=28,cpus=30-31,memdev=ram-node2 \
|
||||
-nographic -monitor unix:/tmp/test-monitor,server,nowait \
|
||||
-no-acpi -boot c -usb -net none -serial none -parallel none
|
@ -1197,7 +1197,14 @@ mymain(void)
|
||||
DO_TEST("blkiotune-device", QEMU_CAPS_NAME);
|
||||
DO_TEST("cputune", QEMU_CAPS_NAME);
|
||||
DO_TEST("cputune-zero-shares", QEMU_CAPS_NAME);
|
||||
|
||||
DO_TEST("numatune-memory", NONE);
|
||||
DO_TEST("numatune-memnode", QEMU_CAPS_NUMA, QEMU_CAPS_OBJECT_MEMORY_RAM);
|
||||
DO_TEST_FAILURE("numatune-memnode", NONE);
|
||||
|
||||
DO_TEST("numatune-memnode-no-memory", QEMU_CAPS_NUMA, QEMU_CAPS_OBJECT_MEMORY_RAM);
|
||||
DO_TEST_FAILURE("numatune-memnode-no-memory", NONE);
|
||||
|
||||
DO_TEST("numatune-auto-nodeset-invalid", NONE);
|
||||
DO_TEST_PARSE_ERROR("numatune-memnode-nocpu", NONE);
|
||||
DO_TEST_PARSE_ERROR("numatune-memnodes-problematic", NONE);
|
||||
|
Loading…
x
Reference in New Issue
Block a user