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);