static int virStorageEncryptionInfoParseCipher(xmlNodePtr info_node, virStorageEncryptionInfoDefPtr info) { int ret = -1; char *size_str = NULL; if (!(info->cipher_name = virXMLPropString(info_node, "name"))) { virReportError(VIR_ERR_XML_ERROR, "%s", _("cipher info missing 'name' attribute")); goto cleanup; } if ((size_str = virXMLPropString(info_node, "size")) && virStrToLong_uip(size_str, NULL, 10, &info->cipher_size) < 0) { virReportError(VIR_ERR_XML_ERROR, _("cannot parse cipher size: '%s'"), size_str); goto cleanup; } if (!size_str) { virReportError(VIR_ERR_XML_ERROR, "%s", _("cipher info missing 'size' attribute")); goto cleanup; } info->cipher_mode = virXMLPropString(info_node, "mode"); info->cipher_hash = virXMLPropString(info_node, "hash"); ret = 0; cleanup: VIR_FREE(size_str); 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 virDomainNumaDefCPUParseXML(virDomainNumaPtr def, xmlXPathContextPtr ctxt) { xmlNodePtr *nodes = NULL; xmlNodePtr oldNode = ctxt->node; char *tmp = NULL; int n; size_t i; int ret = -1; /* check if NUMA definition is present */ if (!virXPathNode("./cpu/numa[1]", ctxt)) return 0; if ((n = virXPathNodeSet("./cpu/numa[1]/cell", ctxt, &nodes)) <= 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("NUMA topology defined without NUMA cells")); goto cleanup; } if (VIR_ALLOC_N(def->mem_nodes, n) < 0) goto cleanup; def->nmem_nodes = n; for (i = 0; i < n; i++) { size_t j; int rc; unsigned int cur_cell = i; /* cells are in order of parsing or explicitly numbered */ if ((tmp = virXMLPropString(nodes[i], "id"))) { if (virStrToLong_uip(tmp, NULL, 10, &cur_cell) < 0) { virReportError(VIR_ERR_XML_ERROR, _("Invalid 'id' attribute in NUMA cell: '%s'"), tmp); goto cleanup; } if (cur_cell >= n) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Exactly one 'cell' element per guest " "NUMA cell allowed, non-contiguous ranges or " "ranges not starting from 0 are not allowed")); goto cleanup; } } VIR_FREE(tmp); if (def->mem_nodes[cur_cell].cpumask) { virReportError(VIR_ERR_XML_ERROR, _("Duplicate NUMA cell info for cell id '%u'"), cur_cell); goto cleanup; } if (!(tmp = virXMLPropString(nodes[i], "cpus"))) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing 'cpus' attribute in NUMA cell")); goto cleanup; } if (virBitmapParse(tmp, 0, &def->mem_nodes[cur_cell].cpumask, VIR_DOMAIN_CPUMASK_LEN) < 0) goto cleanup; if (virBitmapIsAllClear(def->mem_nodes[cur_cell].cpumask)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("NUMA cell %d has no vCPUs assigned"), cur_cell); goto cleanup; } VIR_FREE(tmp); for (j = 0; j < i; j++) { if (virBitmapOverlaps(def->mem_nodes[j].cpumask, def->mem_nodes[i].cpumask)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("NUMA cells %zu and %zu have overlapping vCPU ids"), i, j); goto cleanup; } } ctxt->node = nodes[i]; if (virDomainParseMemory("./@memory", "./@unit", ctxt, &def->mem_nodes[cur_cell].mem, true, false) < 0) goto cleanup; if ((tmp = virXMLPropString(nodes[i], "memAccess"))) { if ((rc = virNumaMemAccessTypeFromString(tmp)) <= 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Invalid 'memAccess' attribute value '%s'"), tmp); goto cleanup; } def->mem_nodes[cur_cell].memAccess = rc; VIR_FREE(tmp); } } ret = 0; cleanup: ctxt->node = oldNode; VIR_FREE(nodes); VIR_FREE(tmp); return ret; }
static int virDomainNumaDefNodeDistanceParseXML(virDomainNumaPtr def, xmlXPathContextPtr ctxt, unsigned int cur_cell) { int ret = -1; int sibling; char *tmp = NULL; xmlNodePtr *nodes = NULL; size_t i, ndistances = def->nmem_nodes; if (ndistances == 0) return 0; /* check if NUMA distances definition is present */ if (!virXPathNode("./distances[1]", ctxt)) return 0; if ((sibling = virXPathNodeSet("./distances[1]/sibling", ctxt, &nodes)) <= 0) { virReportError(VIR_ERR_XML_ERROR, "%s", _("NUMA distances defined without siblings")); goto cleanup; } for (i = 0; i < sibling; i++) { virDomainNumaDistancePtr ldist, rdist; unsigned int sibling_id, sibling_value; /* siblings are in order of parsing or explicitly numbered */ if (!(tmp = virXMLPropString(nodes[i], "id"))) { virReportError(VIR_ERR_XML_ERROR, _("Missing 'id' attribute in NUMA " "distances under 'cell id %d'"), cur_cell); goto cleanup; } /* The "id" needs to be applicable */ if (virStrToLong_uip(tmp, NULL, 10, &sibling_id) < 0) { virReportError(VIR_ERR_XML_ERROR, _("Invalid 'id' attribute in NUMA " "distances for sibling: '%s'"), tmp); goto cleanup; } VIR_FREE(tmp); /* The "id" needs to be within numa/cell range */ if (sibling_id >= ndistances) { virReportError(VIR_ERR_XML_ERROR, _("'sibling_id %d' does not refer to a " "valid cell within NUMA 'cell id %d'"), sibling_id, cur_cell); goto cleanup; } /* We need a locality value. Check and correct * distance to local and distance to remote node. */ if (!(tmp = virXMLPropString(nodes[i], "value"))) { virReportError(VIR_ERR_XML_ERROR, _("Missing 'value' attribute in NUMA distances " "under 'cell id %d' for 'sibling id %d'"), cur_cell, sibling_id); goto cleanup; } /* The "value" needs to be applicable */ if (virStrToLong_uip(tmp, NULL, 10, &sibling_value) < 0) { virReportError(VIR_ERR_XML_ERROR, _("'value %s' is invalid for " "'sibling id %d' under NUMA 'cell id %d'"), tmp, sibling_id, cur_cell); goto cleanup; } VIR_FREE(tmp); /* Assure LOCAL_DISTANCE <= "value" <= UNREACHABLE * and correct LOCAL_DISTANCE setting if such applies. */ if ((sibling_value < LOCAL_DISTANCE || sibling_value > UNREACHABLE) || (sibling_id == cur_cell && sibling_value != LOCAL_DISTANCE) || (sibling_id != cur_cell && sibling_value == LOCAL_DISTANCE)) { virReportError(VIR_ERR_XML_ERROR, _("'value %d' is invalid for " "'sibling id %d' under NUMA 'cell id %d'"), sibling_value, sibling_id, cur_cell); goto cleanup; } /* Apply the local / remote distance */ ldist = def->mem_nodes[cur_cell].distances; if (!ldist) { if (VIR_ALLOC_N(ldist, ndistances) < 0) goto cleanup; ldist[cur_cell].value = LOCAL_DISTANCE; ldist[cur_cell].cellid = cur_cell; def->mem_nodes[cur_cell].ndistances = ndistances; def->mem_nodes[cur_cell].distances = ldist; } ldist[sibling_id].cellid = sibling_id; ldist[sibling_id].value = sibling_value; /* Apply symmetry if none given */ rdist = def->mem_nodes[sibling_id].distances; if (!rdist) { if (VIR_ALLOC_N(rdist, ndistances) < 0) goto cleanup; rdist[sibling_id].value = LOCAL_DISTANCE; rdist[sibling_id].cellid = sibling_id; def->mem_nodes[sibling_id].ndistances = ndistances; def->mem_nodes[sibling_id].distances = rdist; } rdist[cur_cell].cellid = cur_cell; if (!rdist[cur_cell].value) rdist[cur_cell].value = sibling_value; } ret = 0; cleanup: if (ret < 0) { for (i = 0; i < ndistances; i++) VIR_FREE(def->mem_nodes[i].distances); def->mem_nodes[i].ndistances = 0; } VIR_FREE(nodes); VIR_FREE(tmp); return ret; }