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 <mkletzan@redhat.com>
This commit is contained in:
Martin Kletzander 2014-06-09 15:00:22 +02:00
parent e764ec7ae3
commit 93e82727ec
18 changed files with 556 additions and 286 deletions

View File

@ -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

View File

@ -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 <vcpu> 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 <numatune> to <vcpu> if its 'placement'
* is not specified and 'placement' of <numatune> 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 <numatune>
* and 'placement' of <vcpu> 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, "</cputune>\n");
if (def->numatune.memory.nodemask ||
def->numatune.memory.placement_mode) {
const char *mode;
char *nodemask = NULL;
const char *placement;
virBufferAddLit(buf, "<numatune>\n");
virBufferAdjustIndent(buf, 2);
mode = virDomainNumatuneMemModeTypeToString(def->numatune.memory.mode);
virBufferAsprintf(buf, "<memory mode='%s' ", mode);
if (def->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, "</numatune>\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;
}

View File

@ -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 */

View File

@ -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, "<numatune>\n");
virBufferAdjustIndent(buf, 2);
tmp = virDomainNumatuneMemModeTypeToString(numatune->memory.mode);
virBufferAsprintf(buf, "<memory mode='%s' ", tmp);
if (numatune->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, "</numatune>\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;
}

View File

@ -23,9 +23,25 @@
#ifndef __NUMATUNE_CONF_H__
# define __NUMATUNE_CONF_H__
# include <libxml/xpath.h>
# 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__ */

View File

@ -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

View File

@ -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:

View File

@ -653,10 +653,7 @@ static int virLXCControllerGetNumadAdvice(virLXCControllerPtr ctrl,
/* Get the advisory nodeset from numad if 'placement' of
* either <vcpu> or <numatune> 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)

View File

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

View File

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

View File

@ -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)) {

View File

@ -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 = &params[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 {

View File

@ -3898,10 +3898,7 @@ int qemuProcessStart(virConnectPtr conn,
/* Get the advisory nodeset from numad if 'placement' of
* either <vcpu> or <numatune> 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;

View File

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

View File

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

View File

@ -0,0 +1,29 @@
<domain type='qemu'>
<name>QEMUGuest</name>
<uuid>9f4b6512-e73a-4a25-93e8-5307802821ce</uuid>
<memory unit='KiB'>65536</memory>
<currentMemory unit='KiB'>65536</currentMemory>
<vcpu placement='auto'>1</vcpu>
<numatune>
<memory mode='preferred'/>
</numatune>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<cpu>
<numa>
<cell id='0' cpus='0' memory='65536'/>
</numa>
</cpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/kvm</emulator>
<controller type='usb' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>

View File

@ -0,0 +1,29 @@
<domain type='qemu'>
<name>QEMUGuest</name>
<uuid>9f4b6512-e73a-4a25-93e8-5307802821ce</uuid>
<memory unit='KiB'>65536</memory>
<currentMemory unit='KiB'>65536</currentMemory>
<vcpu placement='auto'>1</vcpu>
<numatune>
<memory mode='preferred' placement='auto'/>
</numatune>
<os>
<type arch='x86_64' machine='pc'>hvm</type>
<boot dev='hd'/>
</os>
<cpu>
<numa>
<cell id='0' cpus='0' memory='65536'/>
</numa>
</cpu>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/kvm</emulator>
<controller type='usb' index='0'/>
<controller type='pci' index='0' model='pci-root'/>
<memballoon model='virtio'/>
</devices>
</domain>

View File

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