qemuValidateDomainVCpuTopology: Always validate vcpu count against topology

Historically we've used QEMU_CAPS_QUERY_HOTPLUGGABLE_CPUS as witness
that the topology must cover the maximum number ov vcpus. qemu started
to enforce this in qemu-2.5, thus we can now always do the check.

This change also requires aligning the topology in certain test files.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa 2023-08-15 17:17:14 +02:00
parent 67979c7a63
commit 4bc796a82f
5 changed files with 28 additions and 36 deletions

View File

@ -759,6 +759,9 @@ qemuValidateDomainVCpuTopology(const virDomainDef *def, virQEMUCaps *qemuCaps)
{
unsigned int maxCpus = virQEMUCapsGetMachineMaxCpus(qemuCaps, def->virtType,
def->os.machine);
unsigned int topologycpus;
unsigned int granularity;
unsigned int numacpus;
if (virDomainDefGetVcpus(def) == 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@ -773,42 +776,31 @@ qemuValidateDomainVCpuTopology(const virDomainDef *def, virQEMUCaps *qemuCaps)
return -1;
}
/* QEMU 2.7 (detected via the availability of query-hotpluggable-cpus)
* enforces stricter rules than previous versions when it comes to guest
* CPU topology. Verify known constraints are respected */
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_HOTPLUGGABLE_CPUS)) {
unsigned int topologycpus;
unsigned int granularity;
unsigned int numacpus;
/* Starting from QEMU 2.5, max vCPU count and overall vCPU topology
* must agree. We only actually enforce this with QEMU 2.7+, due
* to the capability check above */
if (virDomainDefGetVcpusTopology(def, &topologycpus) == 0) {
if (topologycpus != virDomainDefGetVcpusMax(def)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("CPU topology doesn't match maximum vcpu count"));
return -1;
}
numacpus = virDomainNumaGetCPUCountTotal(def->numa);
if ((numacpus != 0) && (topologycpus != numacpus)) {
VIR_WARN("CPU topology doesn't match numa CPU count; "
"partial NUMA mapping is obsoleted and will "
"be removed in future");
}
}
/* vCPU hotplug granularity must be respected */
granularity = qemuValidateDefGetVcpuHotplugGranularity(def);
if ((virDomainDefGetVcpus(def) % granularity) != 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("vCPUs count must be a multiple of the vCPU hotplug granularity (%1$u)"),
granularity);
/* Starting from QEMU 2.5, max vCPU count and overall vCPU topology must agree. */
if (virDomainDefGetVcpusTopology(def, &topologycpus) == 0) {
if (topologycpus != virDomainDefGetVcpusMax(def)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("CPU topology doesn't match maximum vcpu count"));
return -1;
}
}
numacpus = virDomainNumaGetCPUCountTotal(def->numa);
if ((numacpus != 0) && (topologycpus != numacpus)) {
VIR_WARN("CPU topology doesn't match numa CPU count; "
"partial NUMA mapping is obsoleted and will "
"be removed in future");
}
/* vCPU hotplug granularity must be respected */
granularity = qemuValidateDefGetVcpuHotplugGranularity(def);
if ((virDomainDefGetVcpus(def) % granularity) != 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("vCPUs count must be a multiple of the vCPU hotplug granularity (%1$u)"),
granularity);
return -1;
}
if (ARCH_IS_X86(def->os.arch) &&
virDomainDefGetVcpusMax(def) > QEMU_MAX_VCPUS_WITHOUT_EIM) {
if (!qemuDomainIsQ35(def)) {

View File

@ -14,7 +14,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-instance-00000092/.config \
-accel kvm \
-m size=29360128k \
-overcommit mem-lock=off \
-smp 20,sockets=1,cores=8,threads=1 \
-smp 20,sockets=1,cores=20,threads=1 \
-object memory-backend-file,id=ram-node0,mem-path=/var/lib/libvirt/qemu/ram/-1-instance-00000092/ram-node0,share=off,prealloc=on,size=15032385536 \
-numa node,nodeid=0,cpus=0-7,cpus=16-19,memdev=ram-node0 \
-object memory-backend-file,id=ram-node1,mem-path=/var/lib/libvirt/qemu/ram/-1-instance-00000092/ram-node1,share=on,prealloc=on,size=15032385536 \

View File

@ -14,7 +14,7 @@
<boot dev='hd'/>
</os>
<cpu>
<topology sockets='1' dies='1' cores='8' threads='1'/>
<topology sockets='1' dies='1' cores='20' threads='1'/>
<numa>
<cell id='0' cpus='0-7,16-19' memory='14680064' unit='KiB'/>
<cell id='1' cpus='8-15' memory='14680064' unit='KiB' memAccess='shared'/>

View File

@ -14,7 +14,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-instance-00000092/.config \
-accel kvm \
-m size=44040192k \
-overcommit mem-lock=off \
-smp 32,sockets=1,cores=24,threads=1 \
-smp 32,sockets=1,cores=32,threads=1 \
-object memory-backend-file,id=ram-node0,mem-path=/var/lib/libvirt/qemu/ram/-1-instance-00000092/ram-node0,share=on,prealloc=on,size=15032385536 \
-numa node,nodeid=0,cpus=0-1,cpus=6-31,memdev=ram-node0 \
-object memory-backend-file,id=ram-node1,mem-path=/var/lib/libvirt/qemu/ram/-1-instance-00000092/ram-node1,share=on,prealloc=on,size=15032385536 \

View File

@ -14,7 +14,7 @@
<boot dev='hd'/>
</os>
<cpu>
<topology sockets='1' dies='1' cores='24' threads='1'/>
<topology sockets='1' dies='1' cores='32' threads='1'/>
<numa>
<cell id='0' cpus='0-1,6-31' memory='14680064' unit='KiB'/>
<cell id='1' cpus='2-3' memory='14680064' unit='KiB' memAccess='shared'/>