int virDomainNumatuneParseXML(virDomainNumaPtr numa, bool placement_static, xmlXPathContextPtr ctxt) { char *tmp = NULL; int mode = -1; int n = 0; int placement = -1; int ret = -1; virBitmapPtr nodeset = NULL; xmlNodePtr node = NULL; if (virXPathInt("count(./numatune)", ctxt, &n) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot extract numatune nodes")); goto cleanup; } else if (n > 1) { virReportError(VIR_ERR_XML_ERROR, "%s", _("only one numatune is supported")); goto cleanup; } node = virXPathNode("./numatune/memory[1]", ctxt); if (!placement_static && !node) placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO; if (node) { if ((tmp = virXMLPropString(node, "mode")) && (mode = virDomainNumatuneMemModeTypeFromString(tmp)) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported NUMA memory tuning mode '%s'"), tmp); goto cleanup; } VIR_FREE(tmp); if ((tmp = virXMLPropString(node, "placement")) && (placement = virDomainNumatunePlacementTypeFromString(tmp)) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported NUMA memory placement mode '%s'"), tmp); goto cleanup; } VIR_FREE(tmp); tmp = virXMLPropString(node, "nodeset"); if (tmp) { if (virBitmapParse(tmp, 0, &nodeset, VIR_DOMAIN_CPUMASK_LEN) < 0) goto cleanup; if (virBitmapIsAllClear(nodeset)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid value of 'nodeset': %s"), tmp); goto cleanup; } VIR_FREE(tmp); } } if (virDomainNumatuneSet(numa, placement_static, placement, mode, nodeset) < 0) goto cleanup; if (virDomainNumatuneNodeParseXML(numa, ctxt) < 0) goto cleanup; ret = 0; cleanup: virBitmapFree(nodeset); VIR_FREE(tmp); return ret; }
static int virDomainNumatuneNodeParseXML(virDomainNumaPtr numa, xmlXPathContextPtr ctxt) { char *tmp = NULL; int n = 0; int ret = -1; size_t i = 0; xmlNodePtr *nodes = NULL; if ((n = virXPathNodeSet("./numatune/memnode", ctxt, &nodes)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Cannot extract memnode nodes")); goto cleanup; } if (!n) return 0; if (numa->memory.specified && numa->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Per-node binding is not compatible with " "automatic NUMA placement.")); goto cleanup; } if (!numa->nmem_nodes) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Element 'memnode' is invalid without " "any guest NUMA cells")); goto cleanup; } for (i = 0; i < n; i++) { int mode = 0; unsigned int cellid = 0; virDomainNumaNodePtr mem_node = NULL; xmlNodePtr cur_node = nodes[i]; tmp = virXMLPropString(cur_node, "cellid"); if (!tmp) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing required cellid attribute " "in memnode element")); goto cleanup; } if (virStrToLong_uip(tmp, NULL, 10, &cellid) < 0) { virReportError(VIR_ERR_XML_ERROR, _("Invalid cellid attribute in memnode element: %s"), tmp); goto cleanup; } VIR_FREE(tmp); if (cellid >= numa->nmem_nodes) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Argument 'cellid' in memnode element must " "correspond to existing guest's NUMA cell")); goto cleanup; } mem_node = &numa->mem_nodes[cellid]; if (mem_node->nodeset) { virReportError(VIR_ERR_XML_ERROR, _("Multiple memnode elements with cellid %u"), cellid); goto cleanup; } tmp = virXMLPropString(cur_node, "mode"); if (!tmp) { mem_node->mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT; } else { if ((mode = virDomainNumatuneMemModeTypeFromString(tmp)) < 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Invalid mode attribute in memnode element")); goto cleanup; } VIR_FREE(tmp); mem_node->mode = mode; } tmp = virXMLPropString(cur_node, "nodeset"); if (!tmp) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing required nodeset attribute " "in memnode element")); goto cleanup; } if (virBitmapParse(tmp, 0, &mem_node->nodeset, VIR_DOMAIN_CPUMASK_LEN) < 0) goto cleanup; if (virBitmapIsAllClear(mem_node->nodeset)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid value of 'nodeset': %s"), tmp); goto cleanup; } VIR_FREE(tmp); } ret = 0; cleanup: VIR_FREE(nodes); VIR_FREE(tmp); return ret; }
int virDomainNumatuneParseXML(virDomainNumatunePtr *numatunePtr, bool placement_static, size_t ncells, xmlXPathContextPtr ctxt) { char *tmp = NULL; int mode = -1; int n = 0; int placement = -1; int ret = -1; virBitmapPtr nodeset = NULL; xmlNodePtr node = NULL; if (virXPathInt("count(./numatune)", ctxt, &n) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot extract numatune nodes")); goto cleanup; } else if (n > 1) { virReportError(VIR_ERR_XML_ERROR, "%s", _("only one numatune is supported")); goto cleanup; } node = virXPathNode("./numatune/memory[1]", ctxt); if (*numatunePtr) { virDomainNumatuneFree(*numatunePtr); *numatunePtr = NULL; } if (!node && placement_static) { if (virDomainNumatuneNodeParseXML(numatunePtr, ncells, ctxt) < 0) goto cleanup; return 0; } if (!node) { /* We know that placement_mode is "auto" if we're here */ ret = virDomainNumatuneSet(numatunePtr, placement_static, VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO, -1, NULL); goto cleanup; } tmp = virXMLPropString(node, "mode"); if (tmp) { mode = virDomainNumatuneMemModeTypeFromString(tmp); if (mode < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported NUMA memory tuning mode '%s'"), tmp); goto cleanup; } } VIR_FREE(tmp); tmp = virXMLPropString(node, "placement"); if (tmp) { placement = virDomainNumatunePlacementTypeFromString(tmp); if (placement < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported NUMA memory placement mode '%s'"), tmp); goto cleanup; } } VIR_FREE(tmp); tmp = virXMLPropString(node, "nodeset"); if (tmp && virBitmapParse(tmp, 0, &nodeset, VIR_DOMAIN_CPUMASK_LEN) < 0) goto cleanup; VIR_FREE(tmp); if (virDomainNumatuneSet(numatunePtr, placement_static, placement, mode, nodeset) < 0) goto cleanup; if (virDomainNumatuneNodeParseXML(numatunePtr, ncells, ctxt) < 0) goto cleanup; ret = 0; cleanup: virBitmapFree(nodeset); VIR_FREE(tmp); return ret; }