From 93e82727ec11d471d2ef3a18835e1fdfe062cef1 Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Mon, 9 Jun 2014 15:00:22 +0200 Subject: [PATCH] numatune: Encapsulate numatune configuration in order to unify results There were numerous places where numatune configuration (and thus domain config as well) was changed in different ways. On some places this even resulted in persistent domain definition not to be stable (it would change with daemon's restart). In order to uniformly change how numatune config is dealt with, all the internals are now accessible directly only in numatune_conf.c and outside this file accessors must be used. Signed-off-by: Martin Kletzander --- po/POTFILES.in | 1 + src/conf/domain_conf.c | 159 +-------- src/conf/domain_conf.h | 8 +- src/conf/numatune_conf.c | 318 ++++++++++++++++++ src/conf/numatune_conf.h | 70 +++- src/libvirt_private.syms | 11 + src/lxc/lxc_cgroup.c | 19 +- src/lxc/lxc_controller.c | 5 +- src/lxc/lxc_native.c | 15 +- src/parallels/parallels_driver.c | 7 +- src/qemu/qemu_cgroup.c | 23 +- src/qemu/qemu_driver.c | 88 +++-- src/qemu/qemu_process.c | 8 +- src/util/virnuma.c | 48 ++- src/util/virnuma.h | 2 +- .../qemuxml2argv-numatune-auto-prefer.xml | 29 ++ .../qemuxml2xmlout-numatune-auto-prefer.xml | 29 ++ tests/qemuxml2xmltest.c | 2 + 18 files changed, 556 insertions(+), 286 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-prefer.xml create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-auto-prefer.xml diff --git a/po/POTFILES.in b/po/POTFILES.in index fd4b56ec08..d10e892a30 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -25,6 +25,7 @@ src/conf/netdev_vlan_conf.c src/conf/netdev_vport_profile_conf.c src/conf/network_conf.c src/conf/node_device_conf.c +src/conf/numatune_conf.c src/conf/nwfilter_conf.c src/conf/nwfilter_params.c src/conf/object_event.c diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d3d1820aec..a1ef374ad5 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2102,7 +2102,7 @@ void virDomainDefFree(virDomainDefPtr def) virDomainVcpuPinDefFree(def->cputune.emulatorpin); - virBitmapFree(def->numatune.memory.nodemask); + virDomainNumatuneFree(def->numatune); virSysinfoDefFree(def->sysinfo); @@ -11332,7 +11332,6 @@ virDomainDefParseXML(xmlDocPtr xml, unsigned long count; bool uuid_generated = false; virHashTablePtr bootHash = NULL; - xmlNodePtr cur; bool usb_none = false; bool usb_other = false; bool usb_master = false; @@ -11794,123 +11793,8 @@ virDomainDefParseXML(xmlDocPtr xml, } } - /* Extract numatune if exists. */ - if ((n = virXPathNodeSet("./numatune", ctxt, &nodes)) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("cannot extract numatune nodes")); + if (virDomainNumatuneParseXML(def, ctxt) < 0) goto error; - } - - if (n > 1) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("only one numatune is supported")); - VIR_FREE(nodes); - goto error; - } - - if (n) { - cur = nodes[0]->children; - while (cur != NULL) { - if (cur->type == XML_ELEMENT_NODE) { - if (xmlStrEqual(cur->name, BAD_CAST "memory")) { - char *mode = NULL; - char *placement = NULL; - char *nodeset = NULL; - - mode = virXMLPropString(cur, "mode"); - if (mode) { - if ((def->numatune.memory.mode = - virDomainNumatuneMemModeTypeFromString(mode)) < 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unsupported NUMA memory " - "tuning mode '%s'"), - mode); - VIR_FREE(mode); - goto error; - } - VIR_FREE(mode); - } else { - def->numatune.memory.mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT; - } - - nodeset = virXMLPropString(cur, "nodeset"); - if (nodeset) { - if (virBitmapParse(nodeset, - 0, - &def->numatune.memory.nodemask, - VIR_DOMAIN_CPUMASK_LEN) < 0) { - VIR_FREE(nodeset); - goto error; - } - VIR_FREE(nodeset); - } - - placement = virXMLPropString(cur, "placement"); - int placement_mode = 0; - if (placement) { - if ((placement_mode = - virDomainNumatunePlacementTypeFromString(placement)) < 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unsupported memory placement " - "mode '%s'"), placement); - VIR_FREE(placement); - goto error; - } - VIR_FREE(placement); - } else if (def->numatune.memory.nodemask) { - /* Defaults to "static" if nodeset is specified. */ - placement_mode = VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC; - } else { - /* Defaults to "placement" of if nodeset is - * not specified. - */ - if (def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_STATIC) - placement_mode = VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC; - else - placement_mode = VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO; - } - - if (placement_mode == VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC && - !def->numatune.memory.nodemask) { - virReportError(VIR_ERR_XML_ERROR, "%s", - _("nodeset for NUMA memory tuning must be set " - "if 'placement' is 'static'")); - goto error; - } - - /* Ignore 'nodeset' if 'placement' is 'auto' finally */ - if (placement_mode == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) { - virBitmapFree(def->numatune.memory.nodemask); - def->numatune.memory.nodemask = NULL; - } - - /* Copy 'placement' of to if its 'placement' - * is not specified and 'placement' of is specified. - */ - if (placement_mode == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO && - !def->cpumask) - def->placement_mode = VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO; - - def->numatune.memory.placement_mode = placement_mode; - } else { - virReportError(VIR_ERR_XML_ERROR, - _("unsupported XML element %s"), - (const char *)cur->name); - goto error; - } - } - cur = cur->next; - } - } else { - /* Defaults NUMA memory placement mode to 'auto' if no - * and 'placement' of is 'auto'. - */ - if (def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) { - def->numatune.memory.placement_mode = VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO; - def->numatune.memory.mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT; - } - } - VIR_FREE(nodes); if ((n = virXPathNodeSet("./resource", ctxt, &nodes)) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -17527,30 +17411,8 @@ virDomainDefFormatInternal(virDomainDefPtr def, def->cputune.emulator_period || def->cputune.emulator_quota) virBufferAddLit(buf, "\n"); - if (def->numatune.memory.nodemask || - def->numatune.memory.placement_mode) { - const char *mode; - char *nodemask = NULL; - const char *placement; - - virBufferAddLit(buf, "\n"); - virBufferAdjustIndent(buf, 2); - mode = virDomainNumatuneMemModeTypeToString(def->numatune.memory.mode); - virBufferAsprintf(buf, "numatune.memory.placement_mode == - VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC) { - if (!(nodemask = virBitmapFormat(def->numatune.memory.nodemask))) - goto error; - virBufferAsprintf(buf, "nodeset='%s'/>\n", nodemask); - VIR_FREE(nodemask); - } else if (def->numatune.memory.placement_mode) { - placement = virDomainNumatunePlacementTypeToString(def->numatune.memory.placement_mode); - virBufferAsprintf(buf, "placement='%s'/>\n", placement); - } - virBufferAdjustIndent(buf, -2); - virBufferAddLit(buf, "\n"); - } + if (virDomainNumatuneFormatXML(buf, def->numatune) < 0) + goto error; if (def->resource) virDomainResourceDefFormat(buf, def->resource); @@ -19847,3 +19709,16 @@ virDomainObjSetMetadata(virDomainObjPtr vm, return 0; } + + +bool +virDomainDefNeedsPlacementAdvice(virDomainDefPtr def) +{ + if (def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) + return true; + + if (virDomainNumatuneHasPlacementAuto(def->numatune)) + return true; + + return false; +} diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 6ed2165d0f..4c9b7e840e 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -67,6 +67,9 @@ typedef virDomainFSDef *virDomainFSDefPtr; typedef struct _virDomainNetDef virDomainNetDef; typedef virDomainNetDef *virDomainNetDefPtr; +typedef struct _virDomainNumatune virDomainNumatune; +typedef virDomainNumatune *virDomainNumatunePtr; + typedef struct _virDomainInputDef virDomainInputDef; typedef virDomainInputDef *virDomainInputDefPtr; @@ -1897,7 +1900,7 @@ struct _virDomainDef { virDomainVcpuPinDefPtr emulatorpin; } cputune; - virDomainNumatune numatune; + virDomainNumatunePtr numatune; virDomainResourceDefPtr resource; virDomainIdMapDef idmap; @@ -2717,4 +2720,7 @@ int virDomainObjSetMetadata(virDomainObjPtr vm, const char *configDir, unsigned int flags); +bool virDomainDefNeedsPlacementAdvice(virDomainDefPtr def) + ATTRIBUTE_NONNULL(1); + #endif /* __DOMAIN_CONF_H */ diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 14300f0d28..6ce1e2d5e3 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -24,6 +24,12 @@ #include "numatune_conf.h" +#include "domain_conf.h" +#include "viralloc.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_DOMAIN + VIR_ENUM_IMPL(virDomainNumatuneMemMode, VIR_DOMAIN_NUMATUNE_MEM_LAST, "strict", @@ -35,3 +41,315 @@ VIR_ENUM_IMPL(virDomainNumatunePlacement, "default", "static", "auto"); + +struct _virDomainNumatune { + struct { + virBitmapPtr nodeset; + virDomainNumatuneMemMode mode; + virDomainNumatunePlacement placement; + } memory; /* pinning for all the memory */ + + /* Future NUMA tuning related stuff should go here. */ +}; + + +int +virDomainNumatuneParseXML(virDomainDefPtr def, + 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 (def->numatune) { + virDomainNumatuneFree(def->numatune); + def->numatune = NULL; + } + + if (!node && def->placement_mode != VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) + return 0; + + if (!node) { + /* We know that def->placement_mode is "auto" if we're here */ + if (virDomainNumatuneSet(def, VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO, + -1, NULL) < 0) + goto cleanup; + return 0; + } + + 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(def, placement, mode, nodeset) < 0) + goto cleanup; + + if (!n) { + ret = 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; + + if (!numatune) + return 0; + + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + + 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); + } + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + return 0; +} + +void +virDomainNumatuneFree(virDomainNumatunePtr numatune) +{ + if (!numatune) + return; + + virBitmapFree(numatune->memory.nodeset); + + VIR_FREE(numatune); +} + +virDomainNumatuneMemMode +virDomainNumatuneGetMode(virDomainNumatunePtr numatune) +{ + return numatune ? numatune->memory.mode : 0; +} + +virBitmapPtr +virDomainNumatuneGetNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset) +{ + if (!numatune) + return NULL; + + if (numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) + return auto_nodeset; + + /* + * This weird logic has the same meaning as switch with + * auto/static/default, but can be more readably changed later. + */ + if (numatune->memory.placement != VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC) + return NULL; + + return numatune->memory.nodeset; +} + +char * +virDomainNumatuneFormatNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset) +{ + return virBitmapFormat(virDomainNumatuneGetNodeset(numatune, + auto_nodeset)); +} + +int +virDomainNumatuneMaybeFormatNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset, + char **mask) +{ + *mask = NULL; + + if (!numatune) + return 0; + + if (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; + } + + *mask = virDomainNumatuneFormatNodeset(numatune, auto_nodeset); + if (!*mask) + return -1; + + return 0; +} + +int +virDomainNumatuneSet(virDomainDefPtr def, + int placement, + int mode, + virBitmapPtr nodeset) +{ + bool create = !def->numatune; /* Whether we are creating new struct */ + int ret = -1; + virDomainNumatunePtr numatune = NULL; + + /* No need to do anything in this case */ + if (mode == -1 && placement == -1 && !nodeset) + return 0; + + /* 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 (create && VIR_ALLOC(def->numatune) < 0) + goto cleanup; + numatune = def->numatune; + + if (create) { + /* Defaults for new struct */ + if (mode == -1) + mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT; + + if (placement == -1) + placement = VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT; + } + + 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 || + def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_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; + } + + if (placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) { + virBitmapFree(numatune->memory.nodeset); + numatune->memory.nodeset = NULL; + if (!def->cpumask) + def->placement_mode = VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO; + } + + if (placement != -1) + numatune->memory.placement = placement; + + ret = 0; + cleanup: + return ret; +} + +bool +virDomainNumatuneEquals(virDomainNumatunePtr n1, + virDomainNumatunePtr n2) +{ + if (!n1 && !n2) + return true; + + if (!n1 || !n2) + return false; + + if (n1->memory.mode != n2->memory.mode) + return false; + + if (n1->memory.placement != n2->memory.placement) + return false; + + return virBitmapEqual(n1->memory.nodeset, n2->memory.nodeset); +} + +bool +virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune) +{ + if (!numatune) + return false; + + if (numatune->memory.placement == VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) + return true; + + return false; +} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index baac7bf7d0..888cff1bf4 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -23,9 +23,25 @@ #ifndef __NUMATUNE_CONF_H__ # define __NUMATUNE_CONF_H__ +# include + # include "internal.h" # include "virutil.h" # include "virbitmap.h" +# include "virbuffer.h" + +/* + * Since numatune configuration is closely bound to the whole config, + * and because we don't have separate domain_conf headers for + * typedefs, structs and functions, we need to have a forward + * declaration here for virDomainDef due to circular dependencies. + */ +typedef struct _virDomainDef virDomainDef; +typedef virDomainDef *virDomainDefPtr; + + +typedef struct _virDomainNumatune virDomainNumatune; +typedef virDomainNumatune *virDomainNumatunePtr; typedef enum { VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT = 0, @@ -36,19 +52,51 @@ typedef enum { } virDomainNumatunePlacement; VIR_ENUM_DECL(virDomainNumatunePlacement) - VIR_ENUM_DECL(virDomainNumatuneMemMode) -typedef struct _virDomainNumatune virDomainNumatune; -typedef virDomainNumatune *virDomainNumatunePtr; -struct _virDomainNumatune { - struct { - virBitmapPtr nodemask; - int mode; /* enum virDomainNumatuneMemMode */ - int placement_mode; /* enum virDomainNumatunePlacement */ - } memory; /* pinning for all the memory */ - /* Future NUMA tuning related stuff should go here. */ -}; +void virDomainNumatuneFree(virDomainNumatunePtr numatune); + +/* + * XML Parse/Format functions + */ +int virDomainNumatuneParseXML(virDomainDefPtr def, xmlXPathContextPtr ctxt) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +int virDomainNumatuneFormatXML(virBufferPtr buf, virDomainNumatunePtr numatune) + ATTRIBUTE_NONNULL(1); + +/* + * Getters + */ +virDomainNumatuneMemMode virDomainNumatuneGetMode(virDomainNumatunePtr numatune); + +virBitmapPtr virDomainNumatuneGetNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset); + +/* + * Formatters + */ +char *virDomainNumatuneFormatNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset); + +int virDomainNumatuneMaybeFormatNodeset(virDomainNumatunePtr numatune, + virBitmapPtr auto_nodeset, + char **mask); + +/* + * Setters + */ +int virDomainNumatuneSet(virDomainDefPtr def, int placement, + int mode, virBitmapPtr nodeset) + ATTRIBUTE_NONNULL(1); + +/* + * Other accessors + */ +bool virDomainNumatuneEquals(virDomainNumatunePtr n1, + virDomainNumatunePtr n2); + +bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune); #endif /* __NUMATUNE_CONF_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index cf8bb91695..0494d9dfae 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -200,6 +200,7 @@ virDomainDefGetDefaultEmulator; virDomainDefGetSecurityLabelDef; virDomainDefMaybeAddController; virDomainDefMaybeAddInput; +virDomainDefNeedsPlacementAdvice; virDomainDefNew; virDomainDefParseFile; virDomainDefParseNode; @@ -607,10 +608,20 @@ virNodeDeviceObjUnlock; # conf/numatune_conf.h +virDomainNumatuneEquals; +virDomainNumatuneFormatNodeset; +virDomainNumatuneFormatXML; +virDomainNumatuneFree; +virDomainNumatuneGetMode; +virDomainNumatuneGetNodeset; +virDomainNumatuneHasPlacementAuto; +virDomainNumatuneMaybeFormatNodeset; virDomainNumatuneMemModeTypeFromString; virDomainNumatuneMemModeTypeToString; +virDomainNumatuneParseXML; virDomainNumatunePlacementTypeFromString; virDomainNumatunePlacementTypeToString; +virDomainNumatuneSet; # conf/nwfilter_conf.h diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index b584e33b2d..cc938239cf 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -79,22 +79,11 @@ static int virLXCCgroupSetupCpusetTune(virDomainDefPtr def, goto cleanup; } - if ((def->numatune.memory.nodemask || - (def->numatune.memory.placement_mode == - VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO)) && - def->numatune.memory.mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) { - if (def->numatune.memory.placement_mode == - VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) - mask = virBitmapFormat(nodemask); - else - mask = virBitmapFormat(def->numatune.memory.nodemask); + if (virDomainNumatuneMaybeFormatNodeset(def->numatune, nodemask, &mask) < 0) + goto cleanup; - if (!mask) - return -1; - - if (virCgroupSetCpusetMems(cgroup, mask) < 0) - goto cleanup; - } + if (mask && virCgroupSetCpusetMems(cgroup, mask) < 0) + goto cleanup; ret = 0; cleanup: diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 03b1d311d7..fd93f479f9 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -653,10 +653,7 @@ static int virLXCControllerGetNumadAdvice(virLXCControllerPtr ctrl, /* Get the advisory nodeset from numad if 'placement' of * either or is 'auto'. */ - if ((ctrl->def->placement_mode == - VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) || - (ctrl->def->numatune.memory.placement_mode == - VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO)) { + if (virDomainDefNeedsPlacementAdvice(ctrl->def)) { nodeset = virNumaGetAutoPlacementAdvice(ctrl->def->vcpus, ctrl->def->mem.cur_balloon); if (!nodeset) diff --git a/src/lxc/lxc_native.c b/src/lxc/lxc_native.c index 30f7e55405..bb15a36ca6 100644 --- a/src/lxc/lxc_native.c +++ b/src/lxc/lxc_native.c @@ -1,6 +1,7 @@ /* * lxc_native.c: LXC native configuration import * + * Copyright (c) 2014 Red Hat, Inc. * Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. * * This library is free software; you can redistribute it and/or @@ -708,6 +709,7 @@ static int lxcSetCpusetTune(virDomainDefPtr def, virConfPtr properties) { virConfValuePtr value; + virBitmapPtr nodeset = NULL; if ((value = virConfGetValue(properties, "lxc.cgroup.cpuset.cpus")) && value->str) { @@ -719,12 +721,15 @@ lxcSetCpusetTune(virDomainDefPtr def, virConfPtr properties) } if ((value = virConfGetValue(properties, "lxc.cgroup.cpuset.mems")) && - value->str) { - def->numatune.memory.placement_mode = VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC; - def->numatune.memory.mode = VIR_DOMAIN_NUMATUNE_MEM_STRICT; - if (virBitmapParse(value->str, 0, &def->numatune.memory.nodemask, - VIR_DOMAIN_CPUMASK_LEN) < 0) + value->str) { + if (virBitmapParse(value->str, 0, &nodeset, VIR_DOMAIN_CPUMASK_LEN) < 0) return -1; + if (virDomainNumatuneSet(def, VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC, + VIR_DOMAIN_NUMATUNE_MEM_STRICT, nodeset) < 0) { + virBitmapFree(nodeset); + return -1; + } + virBitmapFree(nodeset); } return 0; diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c index 43568d1e0a..a503dea932 100644 --- a/src/parallels/parallels_driver.c +++ b/src/parallels/parallels_driver.c @@ -2078,12 +2078,7 @@ parallelsApplyChanges(virDomainObjPtr dom, virDomainDefPtr new) return -1; } - if (old->numatune.memory.mode != new->numatune.memory.mode || - old->numatune.memory.placement_mode != new->numatune.memory.placement_mode || - ((old->numatune.memory.nodemask != NULL || new->numatune.memory.nodemask != NULL) && - (old->numatune.memory.nodemask == NULL || new->numatune.memory.nodemask == NULL || - !virBitmapEqual(old->numatune.memory.nodemask, new->numatune.memory.nodemask)))){ - + if (!virDomainNumatuneEquals(old->numatune, new->numatune)) { virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s", _("numa parameters are not supported " "by parallels driver")); diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c index a24975b17d..dd393eea89 100644 --- a/src/qemu/qemu_cgroup.c +++ b/src/qemu/qemu_cgroup.c @@ -601,23 +601,14 @@ qemuSetupCpusetCgroup(virDomainObjPtr vm, if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPUSET)) return 0; - if ((vm->def->numatune.memory.nodemask || - (vm->def->numatune.memory.placement_mode == - VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO)) && - vm->def->numatune.memory.mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) { + if (virDomainNumatuneMaybeFormatNodeset(vm->def->numatune, + nodemask, + &mem_mask) < 0) + goto cleanup; - if (vm->def->numatune.memory.placement_mode == - VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) - mem_mask = virBitmapFormat(nodemask); - else - mem_mask = virBitmapFormat(vm->def->numatune.memory.nodemask); - - if (!mem_mask) - goto cleanup; - - if (virCgroupSetCpusetMems(priv->cgroup, mem_mask) < 0) - goto cleanup; - } + if (mem_mask && + virCgroupSetCpusetMems(priv->cgroup, mem_mask) < 0) + goto cleanup; if (vm->def->cpumask || (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO)) { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 85c368419f..e166ca431b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -8637,7 +8637,8 @@ qemuDomainSetNumaParamsLive(virDomainObjPtr vm, size_t i = 0; int ret = -1; - if (vm->def->numatune.memory.mode != VIR_DOMAIN_NUMATUNE_MEM_STRICT) { + if (virDomainNumatuneGetMode(vm->def->numatune) != + VIR_DOMAIN_NUMATUNE_MEM_STRICT) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("change of nodeset for running domain " "requires strict numa mode")); @@ -8712,6 +8713,8 @@ qemuDomainSetNumaParameters(virDomainPtr dom, virQEMUDriverConfigPtr cfg = NULL; virCapsPtr caps = NULL; qemuDomainObjPrivatePtr priv; + virBitmapPtr nodeset = NULL; + int mode = -1; virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | VIR_DOMAIN_AFFECT_CONFIG, -1); @@ -8752,65 +8755,47 @@ qemuDomainSetNumaParameters(virDomainPtr dom, virTypedParameterPtr param = ¶ms[i]; if (STREQ(param->field, VIR_DOMAIN_NUMA_MODE)) { - int mode = param->value.i; + mode = param->value.i; - if (mode >= VIR_DOMAIN_NUMATUNE_PLACEMENT_LAST || - mode < VIR_DOMAIN_NUMATUNE_PLACEMENT_DEFAULT) - { + if (mode < 0 || mode >= VIR_DOMAIN_NUMATUNE_MEM_LAST) { virReportError(VIR_ERR_INVALID_ARG, - _("unsupported numa_mode: '%d'"), mode); + _("unsupported numatune mode: '%d'"), mode); goto cleanup; } - if ((flags & VIR_DOMAIN_AFFECT_LIVE) && - vm->def->numatune.memory.mode != mode) { - virReportError(VIR_ERR_OPERATION_INVALID, "%s", - _("can't change numa mode for running domain")); - goto cleanup; - } - - if (flags & VIR_DOMAIN_AFFECT_CONFIG) - persistentDef->numatune.memory.mode = mode; - } else if (STREQ(param->field, VIR_DOMAIN_NUMA_NODESET)) { - virBitmapPtr nodeset = NULL; - if (virBitmapParse(param->value.s, 0, &nodeset, - VIR_DOMAIN_CPUMASK_LEN) < 0) { + VIR_DOMAIN_CPUMASK_LEN) < 0) + goto cleanup; + + if (virBitmapIsAllClear(nodeset)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("Invalid nodeset for numatune")); goto cleanup; } - - if (flags & VIR_DOMAIN_AFFECT_LIVE) { - if (qemuDomainSetNumaParamsLive(vm, caps, nodeset) < 0) { - virBitmapFree(nodeset); - goto cleanup; - } - - /* update vm->def here so that dumpxml can read the new - * values from vm->def. */ - virBitmapFree(vm->def->numatune.memory.nodemask); - - vm->def->numatune.memory.placement_mode = - VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC; - vm->def->numatune.memory.nodemask = virBitmapNewCopy(nodeset); - } - - if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - virBitmapFree(persistentDef->numatune.memory.nodemask); - - persistentDef->numatune.memory.nodemask = nodeset; - persistentDef->numatune.memory.placement_mode = - VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC; - nodeset = NULL; - } - virBitmapFree(nodeset); } } + if (flags & VIR_DOMAIN_AFFECT_LIVE) { + if (mode != -1 && + virDomainNumatuneGetMode(vm->def->numatune) != mode) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("can't change numatune mode for running domain")); + goto cleanup; + } + + if (nodeset && + qemuDomainSetNumaParamsLive(vm, caps, nodeset) < 0) + goto cleanup; + + if (virDomainNumatuneSet(vm->def, -1, mode, nodeset) < 0) + goto cleanup; + } + if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - if (!persistentDef->numatune.memory.placement_mode) - persistentDef->numatune.memory.placement_mode = - VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO; + if (virDomainNumatuneSet(persistentDef, -1, mode, nodeset) < 0) + goto cleanup; + if (virDomainSaveConfig(cfg->configDir, persistentDef) < 0) goto cleanup; } @@ -8818,6 +8803,7 @@ qemuDomainSetNumaParameters(virDomainPtr dom, ret = 0; cleanup: + virBitmapFree(nodeset); if (vm) virObjectUnlock(vm); virObjectUnref(caps); @@ -8886,15 +8872,17 @@ qemuDomainGetNumaParameters(virDomainPtr dom, if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE, VIR_TYPED_PARAM_INT, 0) < 0) goto cleanup; + if (flags & VIR_DOMAIN_AFFECT_CONFIG) - param->value.i = persistentDef->numatune.memory.mode; + param->value.i = virDomainNumatuneGetMode(persistentDef->numatune); else - param->value.i = vm->def->numatune.memory.mode; + param->value.i = virDomainNumatuneGetMode(vm->def->numatune); break; case 1: /* fill numa nodeset here */ if (flags & VIR_DOMAIN_AFFECT_CONFIG) { - nodeset = virBitmapFormat(persistentDef->numatune.memory.nodemask); + nodeset = virDomainNumatuneFormatNodeset(persistentDef->numatune, + NULL); if (!nodeset) goto cleanup; } else { diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index d8bb679990..4c57f15a20 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3898,10 +3898,7 @@ int qemuProcessStart(virConnectPtr conn, /* Get the advisory nodeset from numad if 'placement' of * either or is 'auto'. */ - if ((vm->def->placement_mode == - VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) || - (vm->def->numatune.memory.placement_mode == - VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO)) { + if (virDomainDefNeedsPlacementAdvice(vm->def)) { nodeset = virNumaGetAutoPlacementAdvice(vm->def->vcpus, vm->def->mem.max_balloon); if (!nodeset) @@ -3909,8 +3906,7 @@ int qemuProcessStart(virConnectPtr conn, VIR_DEBUG("Nodeset returned from numad: %s", nodeset); - if (virBitmapParse(nodeset, 0, &nodemask, - VIR_DOMAIN_CPUMASK_LEN) < 0) + if (virBitmapParse(nodeset, 0, &nodemask, VIR_DOMAIN_CPUMASK_LEN) < 0) goto cleanup; } hookData.nodemask = nodemask; diff --git a/src/util/virnuma.c b/src/util/virnuma.c index bc5180a2eb..087f6798d1 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -87,11 +87,10 @@ virNumaGetAutoPlacementAdvice(unsigned short vcpus ATTRIBUTE_UNUSED, #if WITH_NUMACTL int -virNumaSetupMemoryPolicy(virDomainNumatune numatune, +virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, virBitmapPtr nodemask) { nodemask_t mask; - int mode = -1; int node = -1; int ret = -1; int bit = 0; @@ -99,19 +98,9 @@ virNumaSetupMemoryPolicy(virDomainNumatune numatune, int maxnode = 0; virBitmapPtr tmp_nodemask = NULL; - if (numatune.memory.placement_mode == - VIR_DOMAIN_NUMATUNE_PLACEMENT_STATIC) { - if (!numatune.memory.nodemask) - return 0; - VIR_DEBUG("Set NUMA memory policy with specified nodeset"); - tmp_nodemask = numatune.memory.nodemask; - } else if (numatune.memory.placement_mode == - VIR_DOMAIN_NUMATUNE_PLACEMENT_AUTO) { - VIR_DEBUG("Set NUMA memory policy with advisory nodeset from numad"); - tmp_nodemask = nodemask; - } else { + tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask); + if (!tmp_nodemask) return 0; - } if (numa_available() < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -134,13 +123,15 @@ virNumaSetupMemoryPolicy(virDomainNumatune numatune, nodemask_set(&mask, bit); } - mode = numatune.memory.mode; - - if (mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) { + switch (virDomainNumatuneGetMode(numatune)) { + case VIR_DOMAIN_NUMATUNE_MEM_STRICT: numa_set_bind_policy(1); numa_set_membind(&mask); numa_set_bind_policy(0); - } else if (mode == VIR_DOMAIN_NUMATUNE_MEM_PREFERRED) { + break; + + case VIR_DOMAIN_NUMATUNE_MEM_PREFERRED: + { int nnodes = 0; for (i = 0; i < NUMA_NUM_NODES; i++) { if (nodemask_isset(&mask, i)) { @@ -158,17 +149,16 @@ virNumaSetupMemoryPolicy(virDomainNumatune numatune, numa_set_bind_policy(0); numa_set_preferred(node); - } else if (mode == VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE) { - numa_set_interleave_mask(&mask); - } else { - /* XXX: Shouldn't go here, as we already do checking when - * parsing domain XML. - */ - virReportError(VIR_ERR_XML_ERROR, - "%s", _("Invalid mode for memory NUMA tuning.")); - goto cleanup; } + break; + case VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE: + numa_set_interleave_mask(&mask); + break; + + case VIR_DOMAIN_NUMATUNE_MEM_LAST: + break; + } ret = 0; cleanup: @@ -327,10 +317,10 @@ virNumaGetNodeCPUs(int node, #else int -virNumaSetupMemoryPolicy(virDomainNumatune numatune, +virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, virBitmapPtr nodemask ATTRIBUTE_UNUSED) { - if (numatune.memory.nodemask) { + if (virDomainNumatuneGetNodeset(numatune, NULL)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("libvirt is compiled without NUMA tuning support")); diff --git a/src/util/virnuma.h b/src/util/virnuma.h index d2ab6af0aa..13ebec6273 100644 --- a/src/util/virnuma.h +++ b/src/util/virnuma.h @@ -31,7 +31,7 @@ char *virNumaGetAutoPlacementAdvice(unsigned short vcups, unsigned long long balloon); -int virNumaSetupMemoryPolicy(virDomainNumatune numatune, +int virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, virBitmapPtr nodemask); bool virNumaIsAvailable(void); diff --git a/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-prefer.xml b/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-prefer.xml new file mode 100644 index 0000000000..63f0d1fa36 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-numatune-auto-prefer.xml @@ -0,0 +1,29 @@ + + QEMUGuest + 9f4b6512-e73a-4a25-93e8-5307802821ce + 65536 + 65536 + 1 + + + + + hvm + + + + + + + + + destroy + restart + destroy + + /usr/bin/kvm + + + + + diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-auto-prefer.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-auto-prefer.xml new file mode 100644 index 0000000000..19761b42d4 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-numatune-auto-prefer.xml @@ -0,0 +1,29 @@ + + QEMUGuest + 9f4b6512-e73a-4a25-93e8-5307802821ce + 65536 + 65536 + 1 + + + + + hvm + + + + + + + + + destroy + restart + destroy + + /usr/bin/kvm + + + + + diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 172ce2bc3d..8b1b11ad26 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -373,6 +373,8 @@ mymain(void) DO_TEST_DIFFERENT("cpu-numa1"); DO_TEST_DIFFERENT("cpu-numa2"); + DO_TEST_DIFFERENT("numatune-auto-prefer"); + virObjectUnref(driver.caps); virObjectUnref(driver.xmlopt);