From: Peter Krempa Date: Wed, 11 Feb 2015 09:08:35 +0000 (+0100) Subject: conf: Move numatune_conf to numa_conf X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=fcee64e73cae989ac5fb4e005f1e707abf03a128;p=libvirt.git conf: Move numatune_conf to numa_conf For a while now there are two places that gather information about NUMA related guest configuration. While the XML can't be changed we can at least store the data in one place in the definition. Rename the numatune_conf.[ch] files to numa_conf as later patches will move the rest of the definitions from the cpu definition to this one. --- diff --git a/po/POTFILES.in b/po/POTFILES.in index 3064037fcc..c25bfce5bc 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -27,7 +27,7 @@ src/conf/netdev_vport_profile_conf.c src/conf/network_conf.c src/conf/networkcommon_conf.c src/conf/node_device_conf.c -src/conf/numatune_conf.c +src/conf/numa_conf.c src/conf/nwfilter_conf.c src/conf/nwfilter_params.c src/conf/object_event.c diff --git a/src/Makefile.am b/src/Makefile.am index a938d7ea7f..d38432ec2a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -275,7 +275,7 @@ DOMAIN_CONF_SOURCES = \ conf/domain_audit.c conf/domain_audit.h \ conf/domain_nwfilter.c conf/domain_nwfilter.h \ conf/snapshot_conf.c conf/snapshot_conf.h \ - conf/numatune_conf.c conf/numatune_conf.h + conf/numa_conf.c conf/numa_conf.h OBJECT_EVENT_SOURCES = \ conf/object_event.c conf/object_event.h \ diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 325afa82c9..c45e303455 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -38,7 +38,7 @@ # include "virsocketaddr.h" # include "networkcommon_conf.h" # include "nwfilter_params.h" -# include "numatune_conf.h" +# include "numa_conf.h" # include "virnetdevmacvlan.h" # include "virsysinfo.h" # include "virnetdevvportprofile.h" diff --git a/src/conf/numa_conf.c b/src/conf/numa_conf.c new file mode 100644 index 0000000000..0bbc136e59 --- /dev/null +++ b/src/conf/numa_conf.c @@ -0,0 +1,682 @@ +/* + * numa_conf.c + * + * Copyright (C) 2014-2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Author: Martin Kletzander + */ + +#include + +#include "numa_conf.h" + +#include "domain_conf.h" +#include "viralloc.h" +#include "virnuma.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_DOMAIN + +VIR_ENUM_IMPL(virDomainNumatuneMemMode, + VIR_DOMAIN_NUMATUNE_MEM_LAST, + "strict", + "preferred", + "interleave"); + +VIR_ENUM_IMPL(virDomainNumatunePlacement, + VIR_DOMAIN_NUMATUNE_PLACEMENT_LAST, + "default", + "static", + "auto"); + +typedef struct _virDomainNumatuneNode virDomainNumatuneNode; +typedef virDomainNumatuneNode *virDomainNumatuneNodePtr; + +struct _virDomainNumatune { + struct { + bool specified; + virBitmapPtr nodeset; + virDomainNumatuneMemMode mode; + virDomainNumatunePlacement placement; + } memory; /* pinning for all the memory */ + + struct _virDomainNumatuneNode { + virBitmapPtr nodeset; + virDomainNumatuneMemMode mode; + } *mem_nodes; /* fine tuning per guest node */ + size_t nmem_nodes; + + /* Future NUMA tuning related stuff should go here. */ +}; + + +inline bool +virDomainNumatuneNodeSpecified(virDomainNumatunePtr numatune, + int cellid) +{ + if (numatune && + cellid >= 0 && + cellid < numatune->nmem_nodes) + return numatune->mem_nodes[cellid].nodeset; + + return false; +} + +static int +virDomainNumatuneNodeParseXML(virDomainNumatunePtr *numatunePtr, + size_t ncells, + xmlXPathContextPtr ctxt) +{ + char *tmp = NULL; + int n = 0; + int ret = -1; + size_t i = 0; + virDomainNumatunePtr numatune = *numatunePtr; + 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 (numatune && numatune->memory.specified && + numatune->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 (!ncells) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Element 'memnode' is invalid without " + "any guest NUMA cells")); + goto cleanup; + } + + if (!numatune && VIR_ALLOC(numatune) < 0) + goto cleanup; + + *numatunePtr = numatune; + + VIR_FREE(numatune->mem_nodes); + if (VIR_ALLOC_N(numatune->mem_nodes, ncells) < 0) + goto cleanup; + + numatune->nmem_nodes = ncells; + + for (i = 0; i < n; i++) { + int mode = 0; + unsigned int cellid = 0; + virDomainNumatuneNodePtr 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 >= numatune->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 = &numatune->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; + 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; +} + +int +virDomainNumatuneFormatXML(virBufferPtr buf, + virDomainNumatunePtr numatune) +{ + const char *tmp = NULL; + char *nodeset = NULL; + size_t i = 0; + + if (!numatune) + return 0; + + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + + if (numatune->memory.specified) { + tmp = virDomainNumatuneMemModeTypeToString(numatune->memory.mode); + virBufferAsprintf(buf, "memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC) { + if (!(nodeset = virBitmapFormat(numatune->memory.nodeset))) + return -1; + virBufferAsprintf(buf, "nodeset='%s'/>\n", nodeset); + VIR_FREE(nodeset); + } else if (numatune->memory.placement) { + tmp = virDomainNumatunePlacementTypeToString(numatune->memory.placement); + virBufferAsprintf(buf, "placement='%s'/>\n", tmp); + } + } + + for (i = 0; i < numatune->nmem_nodes; i++) { + virDomainNumatuneNodePtr mem_node = &numatune->mem_nodes[i]; + + if (!mem_node->nodeset) + continue; + + if (!(nodeset = virBitmapFormat(mem_node->nodeset))) + return -1; + + virBufferAsprintf(buf, + "\n", + i, + virDomainNumatuneMemModeTypeToString(mem_node->mode), + nodeset); + VIR_FREE(nodeset); + } + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + return 0; +} + +void +virDomainNumatuneFree(virDomainNumatunePtr numatune) +{ + size_t i = 0; + + if (!numatune) + return; + + virBitmapFree(numatune->memory.nodeset); + for (i = 0; i < numatune->nmem_nodes; i++) + virBitmapFree(numatune->mem_nodes[i].nodeset); + VIR_FREE(numatune->mem_nodes); + + VIR_FREE(numatune); +} + +virDomainNumatuneMemMode +virDomainNumatuneGetMode(virDomainNumatunePtr numatune, + int cellid) +{ + if (!numatune) + return 0; + + if (virDomainNumatuneNodeSpecified(numatune, cellid)) + return numatune->mem_nodes[cellid].mode; + + if (numatune->memory.specified) + return numatune->memory.mode; + + return 0; +} + +virBitmapPtr +virDomainNumatuneGetNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset, + int cellid) +{ + if (!numatune) + return NULL; + + if (numatune->memory.specified && + numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) + return auto_nodeset; + + if (virDomainNumatuneNodeSpecified(numatune, cellid)) + return numatune->mem_nodes[cellid].nodeset; + + if (!numatune->memory.specified) + return NULL; + + return numatune->memory.nodeset; +} + +char * +virDomainNumatuneFormatNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset, + int cellid) +{ + return virBitmapFormat(virDomainNumatuneGetNodeset(numatune, + auto_nodeset, + cellid)); +} + + +int +virDomainNumatuneMaybeGetNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset, + virBitmapPtr *retNodeset, + int cellid) +{ + *retNodeset = NULL; + + if (!numatune) + return 0; + + if (!virDomainNumatuneNodeSpecified(numatune, cellid) && + !numatune->memory.specified) + return 0; + + if (numatune->memory.specified && + numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO && + !auto_nodeset) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Advice from numad is needed in case of " + "automatic numa placement")); + return -1; + } + + *retNodeset = virDomainNumatuneGetNodeset(numatune, auto_nodeset, cellid); + + return 0; +} + + +int +virDomainNumatuneMaybeFormatNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset, + char **mask, + int cellid) +{ + virBitmapPtr nodeset; + + if (virDomainNumatuneMaybeGetNodeset(numatune, auto_nodeset, &nodeset, + cellid) < 0) + return -1; + + if (nodeset && + !(*mask = virBitmapFormat(nodeset))) + return -1; + + return 0; +} + +int +virDomainNumatuneSet(virDomainNumatunePtr *numatunePtr, + bool placement_static, + int placement, + int mode, + virBitmapPtr nodeset) +{ + bool created = false; + int ret = -1; + virDomainNumatunePtr numatune; + + /* No need to do anything in this case */ + if (mode == -1 && placement == -1 && !nodeset) + return 0; + + if (!(*numatunePtr)) { + if (VIR_ALLOC(*numatunePtr) < 0) + goto cleanup; + + created = true; + if (mode == -1) + mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT; + if (placement == -1) + placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT; + } + + numatune = *numatunePtr; + + /* Range checks */ + if (mode != -1 && + (mode < 0 || mode >= VIR_DOMAIN_NUMATUNE_MEM_LAST)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unsupported numatune mode '%d'"), + mode); + goto cleanup; + } + + if (placement != -1 && + (placement < 0 || placement >= VIR_DOMAIN_NUMATUNE_PLACEMENT_LAST)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unsupported numatune placement '%d'"), + mode); + goto cleanup; + } + + if (mode != -1) + numatune->memory.mode = mode; + + if (nodeset) { + virBitmapFree(numatune->memory.nodeset); + numatune->memory.nodeset = virBitmapNewCopy(nodeset); + if (!numatune->memory.nodeset) + goto cleanup; + if (placement == -1) + placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC; + } + + if (placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT) { + if (numatune->memory.nodeset || placement_static) + placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC; + else + placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO; + } + + if (placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC && + !numatune->memory.nodeset) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("nodeset for NUMA memory tuning must be set " + "if 'placement' is 'static'")); + goto cleanup; + } + + /* setting nodeset when placement auto is invalid */ + if (placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO && + numatune->memory.nodeset) { + virBitmapFree(numatune->memory.nodeset); + numatune->memory.nodeset = NULL; + } + + if (placement != -1) + numatune->memory.placement = placement; + + numatune->memory.specified = true; + + ret = 0; + + cleanup: + if (ret < 0 && created) { + virDomainNumatuneFree(*numatunePtr); + *numatunePtr = NULL; + } + + return ret; +} + +static bool +virDomainNumatuneNodesEqual(virDomainNumatunePtr n1, + virDomainNumatunePtr n2) +{ + size_t i = 0; + + if (n1->nmem_nodes != n2->nmem_nodes) + return false; + + for (i = 0; i < n1->nmem_nodes; i++) { + virDomainNumatuneNodePtr nd1 = &n1->mem_nodes[i]; + virDomainNumatuneNodePtr nd2 = &n2->mem_nodes[i]; + + if (!nd1->nodeset && !nd2->nodeset) + continue; + + if (nd1->mode != nd2->mode) + return false; + + if (!virBitmapEqual(nd1->nodeset, nd2->nodeset)) + return false; + } + + return true; +} + +bool +virDomainNumatuneEquals(virDomainNumatunePtr n1, + virDomainNumatunePtr n2) +{ + if (!n1 && !n2) + return true; + + if (!n1 || !n2) + return false; + + if (!n1->memory.specified && !n2->memory.specified) + return virDomainNumatuneNodesEqual(n1, n2); + + if (!n1->memory.specified || !n2->memory.specified) + return false; + + if (n1->memory.mode != n2->memory.mode) + return false; + + if (n1->memory.placement != n2->memory.placement) + return false; + + if (!virBitmapEqual(n1->memory.nodeset, n2->memory.nodeset)) + return false; + + return virDomainNumatuneNodesEqual(n1, n2); +} + +bool +virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune) +{ + if (!numatune) + return false; + + if (!numatune->memory.specified) + return false; + + if (numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) + return true; + + return false; +} + +bool +virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune) +{ + size_t i = 0; + + if (!numatune) + return false; + + for (i = 0; i < numatune->nmem_nodes; i++) { + if (numatune->mem_nodes[i].nodeset) + return true; + } + + return false; +} + +int +virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune) +{ + int ret = -1; + virBitmapPtr nodemask = NULL; + size_t i; + int bit; + + if (!numatune) + return ret; + + nodemask = virDomainNumatuneGetNodeset(numatune, NULL, -1); + if (nodemask) + ret = virBitmapLastSetBit(nodemask); + + for (i = 0; i < numatune->nmem_nodes; i++) { + nodemask = numatune->mem_nodes[i].nodeset; + if (!nodemask) + continue; + + bit = virBitmapLastSetBit(nodemask); + if (bit > ret) + ret = bit; + } + + return ret; +} + +bool +virDomainNumatuneNodesetIsAvailable(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset) +{ + size_t i = 0; + virBitmapPtr b = NULL; + + if (!numatune) + return true; + + b = virDomainNumatuneGetNodeset(numatune, auto_nodeset, -1); + if (!virNumaNodesetIsAvailable(b)) + return false; + + for (i = 0; i < numatune->nmem_nodes; i++) { + b = virDomainNumatuneGetNodeset(numatune, auto_nodeset, i); + if (!virNumaNodesetIsAvailable(b)) + return false; + } + + return true; +} diff --git a/src/conf/numa_conf.h b/src/conf/numa_conf.h new file mode 100644 index 0000000000..4891f15694 --- /dev/null +++ b/src/conf/numa_conf.h @@ -0,0 +1,117 @@ +/* + * numa_conf.h + * + * Copyright (C) 2014-2015 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + * Author: Martin Kletzander + */ + +#ifndef __NUMA_CONF_H__ +# define __NUMA_CONF_H__ + +# include + +# include "internal.h" +# include "virutil.h" +# include "virbitmap.h" +# include "virbuffer.h" + + +typedef struct _virDomainNumatune virDomainNumatune; +typedef virDomainNumatune *virDomainNumatunePtr; + +typedef enum { + VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT = 0, + VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC, + VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO, + + VIR_DOMAIN_NUMATUNE_PLACEMENT_LAST +} virDomainNumatunePlacement; + +VIR_ENUM_DECL(virDomainNumatunePlacement) +VIR_ENUM_DECL(virDomainNumatuneMemMode) + + +void virDomainNumatuneFree(virDomainNumatunePtr numatune); + +/* + * XML Parse/Format functions + */ +int virDomainNumatuneParseXML(virDomainNumatunePtr *numatunePtr, + bool placement_static, + size_t ncells, + xmlXPathContextPtr ctxt) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4); + +int virDomainNumatuneFormatXML(virBufferPtr buf, virDomainNumatunePtr numatune) + ATTRIBUTE_NONNULL(1); + +/* + * Getters + */ +virDomainNumatuneMemMode virDomainNumatuneGetMode(virDomainNumatunePtr numatune, + int cellid); + +virBitmapPtr virDomainNumatuneGetNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset, + int cellid); + +int virDomainNumatuneMaybeGetNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset, + virBitmapPtr *retNodeset, + int cellid); + +/* + * Formatters + */ +char *virDomainNumatuneFormatNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset, + int cellid); + +int virDomainNumatuneMaybeFormatNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset, + char **mask, + int cellid); + +/* + * Setters + */ +int virDomainNumatuneSet(virDomainNumatunePtr *numatunePtr, + bool placement_static, + int placement, + int mode, + virBitmapPtr nodeset) + ATTRIBUTE_NONNULL(1); + +/* + * Other accessors + */ +bool virDomainNumatuneEquals(virDomainNumatunePtr n1, + virDomainNumatunePtr n2); + +bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune); + +bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune); + +int virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune); + +bool virDomainNumatuneNodesetIsAvailable(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset); + +bool virDomainNumatuneNodeSpecified(virDomainNumatunePtr numatune, + int cellid); +#endif /* __NUMA_CONF_H__ */ diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c deleted file mode 100644 index d6cedaa5a8..0000000000 --- a/src/conf/numatune_conf.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * numatune_conf.c - * - * Copyright (C) 2014 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see - * . - * - * Author: Martin Kletzander - */ - -#include - -#include "numatune_conf.h" - -#include "domain_conf.h" -#include "viralloc.h" -#include "virnuma.h" -#include "virstring.h" - -#define VIR_FROM_THIS VIR_FROM_DOMAIN - -VIR_ENUM_IMPL(virDomainNumatuneMemMode, - VIR_DOMAIN_NUMATUNE_MEM_LAST, - "strict", - "preferred", - "interleave"); - -VIR_ENUM_IMPL(virDomainNumatunePlacement, - VIR_DOMAIN_NUMATUNE_PLACEMENT_LAST, - "default", - "static", - "auto"); - -typedef struct _virDomainNumatuneNode virDomainNumatuneNode; -typedef virDomainNumatuneNode *virDomainNumatuneNodePtr; - -struct _virDomainNumatune { - struct { - bool specified; - virBitmapPtr nodeset; - virDomainNumatuneMemMode mode; - virDomainNumatunePlacement placement; - } memory; /* pinning for all the memory */ - - struct _virDomainNumatuneNode { - virBitmapPtr nodeset; - virDomainNumatuneMemMode mode; - } *mem_nodes; /* fine tuning per guest node */ - size_t nmem_nodes; - - /* Future NUMA tuning related stuff should go here. */ -}; - - -inline bool -virDomainNumatuneNodeSpecified(virDomainNumatunePtr numatune, - int cellid) -{ - if (numatune && - cellid >= 0 && - cellid < numatune->nmem_nodes) - return numatune->mem_nodes[cellid].nodeset; - - return false; -} - -static int -virDomainNumatuneNodeParseXML(virDomainNumatunePtr *numatunePtr, - size_t ncells, - xmlXPathContextPtr ctxt) -{ - char *tmp = NULL; - int n = 0; - int ret = -1; - size_t i = 0; - virDomainNumatunePtr numatune = *numatunePtr; - 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 (numatune && numatune->memory.specified && - numatune->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 (!ncells) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("Element 'memnode' is invalid without " - "any guest NUMA cells")); - goto cleanup; - } - - if (!numatune && VIR_ALLOC(numatune) < 0) - goto cleanup; - - *numatunePtr = numatune; - - VIR_FREE(numatune->mem_nodes); - if (VIR_ALLOC_N(numatune->mem_nodes, ncells) < 0) - goto cleanup; - - numatune->nmem_nodes = ncells; - - for (i = 0; i < n; i++) { - int mode = 0; - unsigned int cellid = 0; - virDomainNumatuneNodePtr 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 >= numatune->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 = &numatune->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; - 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; -} - -int -virDomainNumatuneFormatXML(virBufferPtr buf, - virDomainNumatunePtr numatune) -{ - const char *tmp = NULL; - char *nodeset = NULL; - size_t i = 0; - - if (!numatune) - return 0; - - virBufferAddLit(buf, "\n"); - virBufferAdjustIndent(buf, 2); - - if (numatune->memory.specified) { - tmp = virDomainNumatuneMemModeTypeToString(numatune->memory.mode); - virBufferAsprintf(buf, "memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC) { - if (!(nodeset = virBitmapFormat(numatune->memory.nodeset))) - return -1; - virBufferAsprintf(buf, "nodeset='%s'/>\n", nodeset); - VIR_FREE(nodeset); - } else if (numatune->memory.placement) { - tmp = virDomainNumatunePlacementTypeToString(numatune->memory.placement); - virBufferAsprintf(buf, "placement='%s'/>\n", tmp); - } - } - - for (i = 0; i < numatune->nmem_nodes; i++) { - virDomainNumatuneNodePtr mem_node = &numatune->mem_nodes[i]; - - if (!mem_node->nodeset) - continue; - - if (!(nodeset = virBitmapFormat(mem_node->nodeset))) - return -1; - - virBufferAsprintf(buf, - "\n", - i, - virDomainNumatuneMemModeTypeToString(mem_node->mode), - nodeset); - VIR_FREE(nodeset); - } - - virBufferAdjustIndent(buf, -2); - virBufferAddLit(buf, "\n"); - return 0; -} - -void -virDomainNumatuneFree(virDomainNumatunePtr numatune) -{ - size_t i = 0; - - if (!numatune) - return; - - virBitmapFree(numatune->memory.nodeset); - for (i = 0; i < numatune->nmem_nodes; i++) - virBitmapFree(numatune->mem_nodes[i].nodeset); - VIR_FREE(numatune->mem_nodes); - - VIR_FREE(numatune); -} - -virDomainNumatuneMemMode -virDomainNumatuneGetMode(virDomainNumatunePtr numatune, - int cellid) -{ - if (!numatune) - return 0; - - if (virDomainNumatuneNodeSpecified(numatune, cellid)) - return numatune->mem_nodes[cellid].mode; - - if (numatune->memory.specified) - return numatune->memory.mode; - - return 0; -} - -virBitmapPtr -virDomainNumatuneGetNodeset(virDomainNumatunePtr numatune, - virBitmapPtr auto_nodeset, - int cellid) -{ - if (!numatune) - return NULL; - - if (numatune->memory.specified && - numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) - return auto_nodeset; - - if (virDomainNumatuneNodeSpecified(numatune, cellid)) - return numatune->mem_nodes[cellid].nodeset; - - if (!numatune->memory.specified) - return NULL; - - return numatune->memory.nodeset; -} - -char * -virDomainNumatuneFormatNodeset(virDomainNumatunePtr numatune, - virBitmapPtr auto_nodeset, - int cellid) -{ - return virBitmapFormat(virDomainNumatuneGetNodeset(numatune, - auto_nodeset, - cellid)); -} - - -int -virDomainNumatuneMaybeGetNodeset(virDomainNumatunePtr numatune, - virBitmapPtr auto_nodeset, - virBitmapPtr *retNodeset, - int cellid) -{ - *retNodeset = NULL; - - if (!numatune) - return 0; - - if (!virDomainNumatuneNodeSpecified(numatune, cellid) && - !numatune->memory.specified) - return 0; - - if (numatune->memory.specified && - numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO && - !auto_nodeset) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Advice from numad is needed in case of " - "automatic numa placement")); - return -1; - } - - *retNodeset = virDomainNumatuneGetNodeset(numatune, auto_nodeset, cellid); - - return 0; -} - - -int -virDomainNumatuneMaybeFormatNodeset(virDomainNumatunePtr numatune, - virBitmapPtr auto_nodeset, - char **mask, - int cellid) -{ - virBitmapPtr nodeset; - - if (virDomainNumatuneMaybeGetNodeset(numatune, auto_nodeset, &nodeset, - cellid) < 0) - return -1; - - if (nodeset && - !(*mask = virBitmapFormat(nodeset))) - return -1; - - return 0; -} - -int -virDomainNumatuneSet(virDomainNumatunePtr *numatunePtr, - bool placement_static, - int placement, - int mode, - virBitmapPtr nodeset) -{ - bool created = false; - int ret = -1; - virDomainNumatunePtr numatune; - - /* No need to do anything in this case */ - if (mode == -1 && placement == -1 && !nodeset) - return 0; - - if (!(*numatunePtr)) { - if (VIR_ALLOC(*numatunePtr) < 0) - goto cleanup; - - created = true; - if (mode == -1) - mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT; - if (placement == -1) - placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT; - } - - numatune = *numatunePtr; - - /* Range checks */ - if (mode != -1 && - (mode < 0 || mode >= VIR_DOMAIN_NUMATUNE_MEM_LAST)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unsupported numatune mode '%d'"), - mode); - goto cleanup; - } - - if (placement != -1 && - (placement < 0 || placement >= VIR_DOMAIN_NUMATUNE_PLACEMENT_LAST)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unsupported numatune placement '%d'"), - mode); - goto cleanup; - } - - if (mode != -1) - numatune->memory.mode = mode; - - if (nodeset) { - virBitmapFree(numatune->memory.nodeset); - numatune->memory.nodeset = virBitmapNewCopy(nodeset); - if (!numatune->memory.nodeset) - goto cleanup; - if (placement == -1) - placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC; - } - - if (placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT) { - if (numatune->memory.nodeset || placement_static) - placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC; - else - placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO; - } - - if (placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC && - !numatune->memory.nodeset) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("nodeset for NUMA memory tuning must be set " - "if 'placement' is 'static'")); - goto cleanup; - } - - /* setting nodeset when placement auto is invalid */ - if (placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO && - numatune->memory.nodeset) { - virBitmapFree(numatune->memory.nodeset); - numatune->memory.nodeset = NULL; - } - - if (placement != -1) - numatune->memory.placement = placement; - - numatune->memory.specified = true; - - ret = 0; - - cleanup: - if (ret < 0 && created) { - virDomainNumatuneFree(*numatunePtr); - *numatunePtr = NULL; - } - - return ret; -} - -static bool -virDomainNumatuneNodesEqual(virDomainNumatunePtr n1, - virDomainNumatunePtr n2) -{ - size_t i = 0; - - if (n1->nmem_nodes != n2->nmem_nodes) - return false; - - for (i = 0; i < n1->nmem_nodes; i++) { - virDomainNumatuneNodePtr nd1 = &n1->mem_nodes[i]; - virDomainNumatuneNodePtr nd2 = &n2->mem_nodes[i]; - - if (!nd1->nodeset && !nd2->nodeset) - continue; - - if (nd1->mode != nd2->mode) - return false; - - if (!virBitmapEqual(nd1->nodeset, nd2->nodeset)) - return false; - } - - return true; -} - -bool -virDomainNumatuneEquals(virDomainNumatunePtr n1, - virDomainNumatunePtr n2) -{ - if (!n1 && !n2) - return true; - - if (!n1 || !n2) - return false; - - if (!n1->memory.specified && !n2->memory.specified) - return virDomainNumatuneNodesEqual(n1, n2); - - if (!n1->memory.specified || !n2->memory.specified) - return false; - - if (n1->memory.mode != n2->memory.mode) - return false; - - if (n1->memory.placement != n2->memory.placement) - return false; - - if (!virBitmapEqual(n1->memory.nodeset, n2->memory.nodeset)) - return false; - - return virDomainNumatuneNodesEqual(n1, n2); -} - -bool -virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune) -{ - if (!numatune) - return false; - - if (!numatune->memory.specified) - return false; - - if (numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) - return true; - - return false; -} - -bool -virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune) -{ - size_t i = 0; - - if (!numatune) - return false; - - for (i = 0; i < numatune->nmem_nodes; i++) { - if (numatune->mem_nodes[i].nodeset) - return true; - } - - return false; -} - -int -virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune) -{ - int ret = -1; - virBitmapPtr nodemask = NULL; - size_t i; - int bit; - - if (!numatune) - return ret; - - nodemask = virDomainNumatuneGetNodeset(numatune, NULL, -1); - if (nodemask) - ret = virBitmapLastSetBit(nodemask); - - for (i = 0; i < numatune->nmem_nodes; i++) { - nodemask = numatune->mem_nodes[i].nodeset; - if (!nodemask) - continue; - - bit = virBitmapLastSetBit(nodemask); - if (bit > ret) - ret = bit; - } - - return ret; -} - -bool -virDomainNumatuneNodesetIsAvailable(virDomainNumatunePtr numatune, - virBitmapPtr auto_nodeset) -{ - size_t i = 0; - virBitmapPtr b = NULL; - - if (!numatune) - return true; - - b = virDomainNumatuneGetNodeset(numatune, auto_nodeset, -1); - if (!virNumaNodesetIsAvailable(b)) - return false; - - for (i = 0; i < numatune->nmem_nodes; i++) { - b = virDomainNumatuneGetNodeset(numatune, auto_nodeset, i); - if (!virNumaNodesetIsAvailable(b)) - return false; - } - - return true; -} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h deleted file mode 100644 index c4b3f6e698..0000000000 --- a/src/conf/numatune_conf.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * numatune_conf.h - * - * Copyright (C) 2014 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see - * . - * - * Author: Martin Kletzander - */ - -#ifndef __NUMATUNE_CONF_H__ -# define __NUMATUNE_CONF_H__ - -# include - -# include "internal.h" -# include "virutil.h" -# include "virbitmap.h" -# include "virbuffer.h" - - -typedef struct _virDomainNumatune virDomainNumatune; -typedef virDomainNumatune *virDomainNumatunePtr; - -typedef enum { - VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT = 0, - VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC, - VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO, - - VIR_DOMAIN_NUMATUNE_PLACEMENT_LAST -} virDomainNumatunePlacement; - -VIR_ENUM_DECL(virDomainNumatunePlacement) -VIR_ENUM_DECL(virDomainNumatuneMemMode) - - -void virDomainNumatuneFree(virDomainNumatunePtr numatune); - -/* - * XML Parse/Format functions - */ -int virDomainNumatuneParseXML(virDomainNumatunePtr *numatunePtr, - bool placement_static, - size_t ncells, - xmlXPathContextPtr ctxt) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4); - -int virDomainNumatuneFormatXML(virBufferPtr buf, virDomainNumatunePtr numatune) - ATTRIBUTE_NONNULL(1); - -/* - * Getters - */ -virDomainNumatuneMemMode virDomainNumatuneGetMode(virDomainNumatunePtr numatune, - int cellid); - -virBitmapPtr virDomainNumatuneGetNodeset(virDomainNumatunePtr numatune, - virBitmapPtr auto_nodeset, - int cellid); - -int virDomainNumatuneMaybeGetNodeset(virDomainNumatunePtr numatune, - virBitmapPtr auto_nodeset, - virBitmapPtr *retNodeset, - int cellid); - -/* - * Formatters - */ -char *virDomainNumatuneFormatNodeset(virDomainNumatunePtr numatune, - virBitmapPtr auto_nodeset, - int cellid); - -int virDomainNumatuneMaybeFormatNodeset(virDomainNumatunePtr numatune, - virBitmapPtr auto_nodeset, - char **mask, - int cellid); - -/* - * Setters - */ -int virDomainNumatuneSet(virDomainNumatunePtr *numatunePtr, - bool placement_static, - int placement, - int mode, - virBitmapPtr nodeset) - ATTRIBUTE_NONNULL(1); - -/* - * Other accessors - */ -bool virDomainNumatuneEquals(virDomainNumatunePtr n1, - virDomainNumatunePtr n2); - -bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune); - -bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune); - -int virDomainNumatuneSpecifiedMaxNode(virDomainNumatunePtr numatune); - -bool virDomainNumatuneNodesetIsAvailable(virDomainNumatunePtr numatune, - virBitmapPtr auto_nodeset); - -bool virDomainNumatuneNodeSpecified(virDomainNumatunePtr numatune, - int cellid); -#endif /* __NUMATUNE_CONF_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 46a16136ca..96291953b1 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -625,7 +625,7 @@ virNodeDeviceObjRemove; virNodeDeviceObjUnlock; -# conf/numatune_conf.h +# conf/numa_conf.h virDomainNumatuneEquals; virDomainNumatuneFormatNodeset; virDomainNumatuneFormatXML;