From 62065a6cb54b2a3d4f4662aa8244a68b3a0fa8d5 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Mon, 9 Dec 2019 20:15:12 -0300 Subject: [PATCH] qemu: command: move NUMA validation to qemu_domain.c A new qemuDomainDefValidateNuma() function was created to host all the QEMU caps validation being done inside qemuBuildNumaArgStr(). This new function is called by qemuDomainValidateCpuCount() to allow NUMA validation in domain define time. Tests were changed to account for the QEMU capabilities that need to be present at domain define time. Reviewed-by: Cole Robinson Signed-off-by: Daniel Henrique Barboza --- src/qemu/qemu_command.c | 42 ------------------------- src/qemu/qemu_domain.c | 66 ++++++++++++++++++++++++++++++++++++++++ tests/qemuxml2argvtest.c | 14 ++++----- tests/qemuxml2xmltest.c | 51 +++++++++++++++++-------------- 4 files changed, 102 insertions(+), 71 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 3126467420..deaf04f1b2 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7447,26 +7447,6 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, int rc; int ret = -1; size_t ncells = virDomainNumaGetNodeCount(def->numa); - const long system_page_size = virGetSystemPageSizeKB(); - - if (virDomainNumatuneHasPerNodeBinding(def->numa) && - !(virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) || - virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE) || - virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD))) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Per-node memory binding is not supported " - "with this QEMU")); - goto cleanup; - } - - if (def->mem.nhugepages && - def->mem.hugepages[0].size != system_page_size && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("huge pages per NUMA node are not " - "supported with this QEMU")); - goto cleanup; - } if (!virDomainNumatuneNodesetIsAvailable(def->numa, priv->autoNodeset)) goto cleanup; @@ -7487,13 +7467,6 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, if (rc == 0) needBackend = true; - } else { - if (virDomainNumaGetNodeMemoryAccessMode(def->numa, i)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Shared memory mapping is not supported " - "with this QEMU")); - goto cleanup; - } } } @@ -7506,14 +7479,6 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, if (!(cpumask = virBitmapFormat(virDomainNumaGetNodeCpumask(def->numa, i)))) goto cleanup; - if (strchr(cpumask, ',') && - !virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("disjoint NUMA cpu ranges are not supported " - "with this QEMU")); - goto cleanup; - } - if (needBackend) { virCommandAddArg(cmd, "-object"); virCommandAddArgBuffer(cmd, &nodeBackends[i]); @@ -7542,13 +7507,6 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg, * of nodes, we have to specify all the distances. Even * though they might be the default ones. */ if (virDomainNumaNodesDistancesAreBeingSet(def->numa)) { - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA_DIST)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("setting NUMA distances is not " - "supported with this qemu")); - goto cleanup; - } - for (i = 0; i < ncells; i++) { for (j = 0; j < ncells; j++) { size_t distance = virDomainNumaGetNodeDistance(def->numa, i, j); diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 93c6af3bc6..432af66fa5 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5225,6 +5225,69 @@ qemuDomainDefValidateMemory(const virDomainDef *def, } +static int +qemuDomainDefValidateNuma(const virDomainDef *def, + virQEMUCapsPtr qemuCaps) +{ + const long system_page_size = virGetSystemPageSizeKB(); + size_t ncells = virDomainNumaGetNodeCount(def->numa); + size_t i; + bool hasMemoryCap = virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM) || + virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE) || + virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_MEMFD); + + if (virDomainNumatuneHasPerNodeBinding(def->numa) && !hasMemoryCap) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Per-node memory binding is not supported " + "with this QEMU")); + return -1; + } + + if (def->mem.nhugepages && + def->mem.hugepages[0].size != system_page_size && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("huge pages per NUMA node are not " + "supported with this QEMU")); + return -1; + } + + for (i = 0; i < ncells; i++) { + g_autofree char * cpumask = NULL; + + if (!hasMemoryCap && + virDomainNumaGetNodeMemoryAccessMode(def->numa, i)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Shared memory mapping is not supported " + "with this QEMU")); + return -1; + } + + if (!(cpumask = virBitmapFormat(virDomainNumaGetNodeCpumask(def->numa, i)))) + return -1; + + if (strchr(cpumask, ',') && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("disjoint NUMA cpu ranges are not supported " + "with this QEMU")); + return -1; + } + + } + + if (virDomainNumaNodesDistancesAreBeingSet(def->numa) && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_NUMA_DIST)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("setting NUMA distances is not " + "supported with this qemu")); + return -1; + } + + return 0; +} + + static int qemuDomainValidateCpuCount(const virDomainDef *def, virQEMUCapsPtr qemuCaps) @@ -5412,6 +5475,9 @@ qemuDomainDefValidate(const virDomainDef *def, if (qemuDomainDefValidateMemory(def, qemuCaps) < 0) goto cleanup; + if (qemuDomainDefValidateNuma(def, qemuCaps) < 0) + goto cleanup; + if (cfg->vncTLS && cfg->vncTLSx509secretUUID && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_TLS_CREDS_X509)) { for (i = 0; i < def->ngraphics; i++) { diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 97e79bcb92..855784e77a 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -944,11 +944,11 @@ mymain(void) QEMU_CAPS_DEVICE_PC_DIMM, QEMU_CAPS_OBJECT_MEMORY_FILE, QEMU_CAPS_OBJECT_MEMORY_FILE_DISCARD); - DO_TEST("hugepages-default", NONE); - DO_TEST("hugepages-default-2M", NONE); + DO_TEST("hugepages-default", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-default-2M", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("hugepages-default-system-size", NONE); DO_TEST_PARSE_ERROR("hugepages-default-1G-nodeset-2M", NONE); - DO_TEST("hugepages-nodeset", NONE); + DO_TEST("hugepages-nodeset", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST_PARSE_ERROR("hugepages-nodeset-nonexist", QEMU_CAPS_DEVICE_PC_DIMM, QEMU_CAPS_OBJECT_MEMORY_FILE, @@ -1711,10 +1711,10 @@ mymain(void) DO_TEST("cpu-numa2", NONE); DO_TEST("cpu-numa-no-memory-element", NONE); DO_TEST_PARSE_ERROR("cpu-numa3", NONE); - DO_TEST_FAILURE("cpu-numa-disjoint", NONE); + DO_TEST_PARSE_ERROR("cpu-numa-disjoint", NONE); DO_TEST("cpu-numa-disjoint", QEMU_CAPS_NUMA); DO_TEST_FAILURE("cpu-numa-memshared", QEMU_CAPS_OBJECT_MEMORY_RAM); - DO_TEST_FAILURE("cpu-numa-memshared", NONE); + DO_TEST_PARSE_ERROR("cpu-numa-memshared", NONE); DO_TEST("cpu-numa-memshared", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("cpu-host-model", NONE); DO_TEST("cpu-host-model-vendor", NONE); @@ -1777,12 +1777,12 @@ mymain(void) DO_TEST("numatune-memnode", QEMU_CAPS_NUMA, QEMU_CAPS_OBJECT_MEMORY_RAM); - DO_TEST_FAILURE("numatune-memnode", NONE); + DO_TEST_PARSE_ERROR("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_PARSE_ERROR("numatune-memnode-no-memory", NONE); DO_TEST("numatune-distances", QEMU_CAPS_NUMA, QEMU_CAPS_NUMA_DIST); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 67309f09ec..8e19ef1b33 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -289,20 +289,21 @@ mymain(void) DO_TEST("pmu-feature-off", NONE); DO_TEST("pages-discard", NONE); - DO_TEST("pages-discard-hugepages", NONE); + DO_TEST("pages-discard-hugepages", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("pages-dimm-discard", NONE); - DO_TEST("hugepages-default", NONE); - DO_TEST("hugepages-default-2M", NONE); + DO_TEST("hugepages-default", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-default-2M", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("hugepages-default-system-size", NONE); - DO_TEST("hugepages-nodeset", NONE); - DO_TEST("hugepages-numa-default-2M", NONE); - DO_TEST("hugepages-numa-default-dimm", NONE); - DO_TEST("hugepages-numa-nodeset", NONE); - DO_TEST("hugepages-numa-nodeset-part", NONE); - DO_TEST("hugepages-shared", NONE); - DO_TEST("hugepages-memaccess", NONE); - DO_TEST("hugepages-memaccess2", NONE); - DO_TEST("hugepages-nvdimm", NONE); + DO_TEST("hugepages-nodeset", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-numa-default-2M", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-numa-default-dimm", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-numa-nodeset", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-numa-nodeset-part", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-shared", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-memaccess", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-memaccess2", QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("hugepages-nvdimm", QEMU_CAPS_DEVICE_NVDIMM, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("nosharepages", NONE); DO_TEST("restore-v2", NONE); DO_TEST("migrate", NONE); @@ -490,7 +491,8 @@ mymain(void) DO_TEST("event_idx", NONE); DO_TEST("vhost_queues", NONE); DO_TEST("interface-driver", NONE); - DO_TEST("interface-server", QEMU_CAPS_DEVICE_CIRRUS_VGA); + DO_TEST("interface-server", QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("virtio-lun", NONE); DO_TEST("usb-none", NONE); @@ -538,7 +540,8 @@ mymain(void) DO_TEST("seclabel-dynamic-none", NONE); DO_TEST("seclabel-device-multiple", NONE); DO_TEST_FULL("seclabel-dynamic-none-relabel", WHEN_INACTIVE, - ARG_QEMU_CAPS, QEMU_CAPS_DEVICE_CIRRUS_VGA, NONE); + ARG_QEMU_CAPS, QEMU_CAPS_DEVICE_CIRRUS_VGA, + QEMU_CAPS_OBJECT_MEMORY_FILE, NONE); DO_TEST("numad-static-vcpu-no-numatune", NONE); DO_TEST("disk-scsi-lun-passthrough-sgio", @@ -572,7 +575,8 @@ mymain(void) DO_TEST("pseries-phb-numa-node", QEMU_CAPS_NUMA, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, - QEMU_CAPS_SPAPR_PCI_HOST_BRIDGE_NUMA_NODE); + QEMU_CAPS_SPAPR_PCI_HOST_BRIDGE_NUMA_NODE, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("pseries-many-devices", QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE, @@ -1006,12 +1010,12 @@ mymain(void) DO_TEST("cpu-numa2", NONE); DO_TEST("cpu-numa-no-memory-element", NONE); DO_TEST("cpu-numa-disordered", NONE); - DO_TEST("cpu-numa-disjoint", NONE); - DO_TEST("cpu-numa-memshared", NONE); + DO_TEST("cpu-numa-disjoint", QEMU_CAPS_NUMA); + DO_TEST("cpu-numa-memshared", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("numatune-auto-prefer", NONE); - DO_TEST("numatune-memnode", NONE); - DO_TEST("numatune-memnode-no-memory", NONE); + DO_TEST("numatune-memnode", QEMU_CAPS_NUMA, QEMU_CAPS_OBJECT_MEMORY_FILE); + DO_TEST("numatune-memnode-no-memory", QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("bios-nvram", NONE); DO_TEST("bios-nvram-os-interleave", NONE); @@ -1200,10 +1204,12 @@ mymain(void) DO_TEST("memfd-memory-numa", QEMU_CAPS_OBJECT_MEMORY_MEMFD, - QEMU_CAPS_OBJECT_MEMORY_MEMFD_HUGETLB); + QEMU_CAPS_OBJECT_MEMORY_MEMFD_HUGETLB, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("memfd-memory-default-hugepage", QEMU_CAPS_OBJECT_MEMORY_MEMFD, - QEMU_CAPS_OBJECT_MEMORY_MEMFD_HUGETLB); + QEMU_CAPS_OBJECT_MEMORY_MEMFD_HUGETLB, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("acpi-table", NONE); @@ -1264,7 +1270,8 @@ mymain(void) DO_TEST("user-aliases", QEMU_CAPS_DEVICE_CIRRUS_VGA, - QEMU_CAPS_QCOW2_LUKS); + QEMU_CAPS_QCOW2_LUKS, + QEMU_CAPS_OBJECT_MEMORY_FILE); DO_TEST("input-virtio-ccw", QEMU_CAPS_CCW, QEMU_CAPS_VIRTIO_KEYBOARD,