On Wed, Dec 16, 2009 at 12:03:59AM +0100, Jiri Denemark wrote: > > Signed-off-by: Jiri Denemark <jdenemar@xxxxxxxxxx> > --- > include/libvirt/virterror.h | 1 + > src/Makefile.am | 9 +- > src/conf/capabilities.c | 31 ++++- > src/conf/capabilities.h | 6 + > src/conf/cpu_conf.c | 366 +++++++++++++++++++++++++++++++++++++++++++ > src/conf/cpu_conf.h | 116 ++++++++++++++ > src/conf/domain_conf.c | 15 ++ > src/conf/domain_conf.h | 2 + > src/libvirt_private.syms | 9 + > src/util/virterror.c | 3 + > 10 files changed, 555 insertions(+), 3 deletions(-) > create mode 100644 src/conf/cpu_conf.c > create mode 100644 src/conf/cpu_conf.h > > diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h > index 8548a8d..30f88e8 100644 > --- a/include/libvirt/virterror.h > +++ b/include/libvirt/virterror.h > @@ -68,6 +68,7 @@ typedef enum { > VIR_FROM_ESX, /* Error from ESX driver */ > VIR_FROM_PHYP, /* Error from IBM power hypervisor */ > VIR_FROM_SECRET, /* Error from secret storage */ > + VIR_FROM_CPU, /* Error from CPU driver */ > } virErrorDomain; > > > diff --git a/src/Makefile.am b/src/Makefile.am > index b639915..432a66e 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -114,6 +114,9 @@ NODE_DEVICE_CONF_SOURCES = \ > ENCRYPTION_CONF_SOURCES = \ > conf/storage_encryption_conf.c conf/storage_encryption_conf.h > > +CPU_CONF_SOURCES = \ > + conf/cpu_conf.c conf/cpu_conf.h > + > CONF_SOURCES = \ > $(DOMAIN_CONF_SOURCES) \ > $(DOMAIN_EVENT_SOURCES) \ > @@ -122,7 +125,8 @@ CONF_SOURCES = \ > $(STORAGE_CONF_SOURCES) \ > $(ENCRYPTION_CONF_SOURCES) \ > $(INTERFACE_CONF_SOURCES) \ > - $(SECRET_CONF_SOURCES) > + $(SECRET_CONF_SOURCES) \ > + $(CPU_CONF_SOURCES) > > # The remote RPC driver, covering domains, storage, networks, etc > REMOTE_DRIVER_SOURCES = \ > @@ -831,7 +835,8 @@ libvirt_lxc_SOURCES = \ > $(UTIL_SOURCES) \ > $(NODE_INFO_SOURCES) \ > $(ENCRYPTION_CONF_SOURCES) \ > - $(DOMAIN_CONF_SOURCES) > + $(DOMAIN_CONF_SOURCES) \ > + $(CPU_CONF_SOURCES) > libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDCFLAGS) $(CAPNG_LIBS) $(YAJL_LIBS) > libvirt_lxc_LDADD = $(LIBXML_LIBS) $(NUMACTL_LIBS) ../gnulib/lib/libgnu.la > libvirt_lxc_CFLAGS = \ > diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c > index 476bba6..47976af 100644 > --- a/src/conf/capabilities.c > +++ b/src/conf/capabilities.c > @@ -27,6 +27,7 @@ > #include "buf.h" > #include "memory.h" > #include "util.h" > +#include "cpu_conf.h" > > /** > * virCapabilitiesNew: > @@ -171,6 +172,8 @@ virCapabilitiesFree(virCapsPtr caps) { > VIR_FREE(caps->host.arch); > VIR_FREE(caps->host.secModel.model); > VIR_FREE(caps->host.secModel.doi); > + virCPUDefFree(caps->host.cpu); > + > VIR_FREE(caps); > } > > @@ -263,6 +266,27 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps, > return 0; > } > > + > +/** > + * virCapabilitiesSetHostCPU: > + * @caps: capabilities to extend > + * @cpu: CPU definition > + * > + * Sets host CPU specification > + */ > +int > +virCapabilitiesSetHostCPU(virCapsPtr caps, > + virCPUDefPtr cpu) > +{ > + if (cpu == NULL) > + return -1; > + > + caps->host.cpu = cpu; > + > + return 0; > +} > + > + > /** > * virCapabilitiesAllocMachines: > * @machines: machine variants for emulator ('pc', or 'isapc', etc) > @@ -653,6 +677,10 @@ virCapabilitiesFormatXML(virCapsPtr caps) > } > virBufferAddLit(&xml, " </features>\n"); > } > + > + virCPUDefFormatBuf(NULL, &xml, caps->host.cpu, " ", > + VIR_CPU_FORMAT_EMBEDED); > + > virBufferAddLit(&xml, " </cpu>\n"); > > if (caps->host.offlineMigrate) { > @@ -750,7 +778,8 @@ virCapabilitiesFormatXML(virCapsPtr caps) > for (j = 0 ; j < caps->guests[i]->nfeatures ; j++) { > if (STREQ(caps->guests[i]->features[j]->name, "pae") || > STREQ(caps->guests[i]->features[j]->name, "nonpae") || > - STREQ(caps->guests[i]->features[j]->name, "ia64_be")) { > + STREQ(caps->guests[i]->features[j]->name, "ia64_be") || > + STREQ(caps->guests[i]->features[j]->name, "cpuselection")) { > virBufferVSprintf(&xml, " <%s/>\n", > caps->guests[i]->features[j]->name); > } else { > diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h > index f8cbae6..8c20cd4 100644 > --- a/src/conf/capabilities.h > +++ b/src/conf/capabilities.h > @@ -27,6 +27,7 @@ > #include "internal.h" > #include "util.h" > #include "buf.h" > +#include "cpu_conf.h" > > #include <libxml/xpath.h> > > @@ -108,6 +109,7 @@ struct _virCapsHost { > int nnumaCell; > virCapsHostNUMACellPtr *numaCell; > virCapsHostSecModel secModel; > + virCPUDefPtr cpu; > }; > > typedef struct _virCaps virCaps; > @@ -166,6 +168,10 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps, > const int *cpus); > > > +extern int > +virCapabilitiesSetHostCPU(virCapsPtr caps, > + virCPUDefPtr cpu); > + > > extern virCapsGuestMachinePtr * > virCapabilitiesAllocMachines(const char *const *names, > diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c > new file mode 100644 > index 0000000..8286eb6 > --- /dev/null > +++ b/src/conf/cpu_conf.c > @@ -0,0 +1,366 @@ > +/* > + * cpu_conf.h: CPU XML handling > + * > + * Copyright (C) 2009 Red Hat, Inc. > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + * > + * Authors: > + * Jiri Denemark <jdenemar@xxxxxxxxxx> > + */ > + > +#include <config.h> > + > +#include "c-ctype.h" > +#include "virterror_internal.h" > +#include "memory.h" > +#include "util.h" > +#include "buf.h" > +#include "cpu_conf.h" > + > +#define VIR_FROM_THIS VIR_FROM_CPU > + > +#define virCPUReportError(conn, code, fmt...) \ > + virReportErrorHelper(conn, VIR_FROM_CPU, code, __FILE__, \ > + __FUNCTION__, __LINE__, fmt) > + > +VIR_ENUM_IMPL(virCPUMatch, VIR_CPU_MATCH_LAST, > + "minimum", > + "exact", > + "strict") > + > +VIR_ENUM_IMPL(virCPUFeaturePolicy, VIR_CPU_FEATURE_LAST, > + "force", > + "require", > + "optional", > + "disable", > + "forbid") > + > + > +void > +virCPUDefFree(virCPUDefPtr def) > +{ > + unsigned int i; > + > + if (!def) > + return; > + > + VIR_FREE(def->model); > + VIR_FREE(def->arch); > + > + for (i = 0 ; i < def->nfeatures ; i++) > + VIR_FREE(def->features[i].name); > + VIR_FREE(def->features); > + > + VIR_FREE(def); > +} > + > + > +virCPUDefPtr > +virCPUDefParseXML(virConnectPtr conn, > + const xmlNodePtr node, > + xmlXPathContextPtr ctxt, > + enum virCPUType mode) > +{ > + virCPUDefPtr def; > + xmlNodePtr *nodes = NULL; > + char *match; > + int n; > + unsigned int i; > + > + if (VIR_ALLOC(def) < 0) { > + virReportOOMError(conn); > + return NULL; > + } > + > + match = virXMLPropString(node, "match"); > + > + if (mode == VIR_CPU_TYPE_AUTO) > + def->type = (match == NULL) ? VIR_CPU_TYPE_HOST : VIR_CPU_TYPE_GUEST; > + else > + def->type = mode; > + > + if (def->type == VIR_CPU_TYPE_GUEST) { > + if ((def->match = virCPUMatchTypeFromString(match)) < 0) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + "%s", _("Invalid match attribute for CPU specification")); > + goto error; > + } > + } > + > + if (def->type == VIR_CPU_TYPE_HOST) { > + def->arch = virXPathString(conn, "string(./arch[1])", ctxt); > + if (!def->arch) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + "%s", _("Missing CPU architecture")); > + goto error; > + } > + } > + > + if (!(def->model = virXPathString(conn, "string(./model[1])", ctxt))) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + "%s", _("Missing CPU model name")); > + goto error; > + } > + > + if (virXPathNode(conn, "./topology[1]", ctxt)) { > + int ret; > + unsigned long ul; > + > + ret = virXPathULong(conn, "string(./topology[1]/@sockets)", > + ctxt, &ul); > + if (ret < 0) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + "%s", _("Missing 'sockets' attribute in CPU topology")); > + goto error; > + } > + def->sockets = (unsigned int) ul; > + > + ret = virXPathULong(conn, "string(./topology[1]/@cores)", > + ctxt, &ul); > + if (ret < 0) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + "%s", _("Missing 'cores' attribute in CPU topology")); > + goto error; > + } > + def->cores = (unsigned int) ul; > + > + ret = virXPathULong(conn, "string(./topology[1]/@threads)", > + ctxt, &ul); > + if (ret < 0) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + "%s", _("Missing 'threads' attribute in CPU topology")); > + goto error; > + } > + def->threads = (unsigned int) ul; > + > + if (!def->sockets || !def->cores || !def->threads) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + "%s", _("Invalid CPU topology")); > + goto error; > + } > + } > + > + n = virXPathNodeSet(conn, "./feature", ctxt, &nodes); > + if (n < 0) > + goto error; > + > + if (n > 0) { > + if (VIR_ALLOC_N(def->features, n) < 0) > + goto no_memory; > + def->nfeatures = n; > + } > + > + for (i = 0 ; i < n ; i++) { > + char *name; > + int policy; /* enum virDomainCPUFeaturePolicy */ > + unsigned int j; > + > + if (def->type == VIR_CPU_TYPE_GUEST) { > + char *strpolicy; > + > + strpolicy = virXMLPropString(nodes[i], "policy"); > + policy = virCPUFeaturePolicyTypeFromString(strpolicy); > + VIR_FREE(strpolicy); > + > + if (policy < 0) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + "%s", _("Invalid CPU feature policy")); > + goto error; > + } > + } > + else > + policy = -1; > + > + if (!(name = virXMLPropString(nodes[i], "name")) || *name == 0) { > + VIR_FREE(name); > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + "%s", _("Invalid CPU feature name")); > + goto error; > + } > + > + for (j = 0 ; j < i ; j++) { > + if (STREQ(name, def->features[j].name)) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + _("CPU feature `%s' specified more than once"), > + name); > + VIR_FREE(name); > + goto error; > + } > + } > + > + def->features[i].name = name; > + def->features[i].policy = policy; > + } > + > +cleanup: > + VIR_FREE(match); > + VIR_FREE(nodes); > + > + return def; > + > +no_memory: > + virReportOOMError(conn); > + > +error: > + virCPUDefFree(def); > + def = NULL; > + goto cleanup; > +} > + > + > +char * > +virCPUDefFormat(virConnectPtr conn, > + virCPUDefPtr def, > + const char *indent, > + int flags) > +{ > + virBuffer buf = VIR_BUFFER_INITIALIZER; > + char *tmp; > + > + if (virCPUDefFormatBuf(conn, &buf, def, indent, flags) < 0) > + goto cleanup; > + > + if (virBufferError(&buf)) > + goto no_memory; > + > + return virBufferContentAndReset(&buf); > + > +no_memory: > + virReportOOMError(conn); > +cleanup: > + tmp = virBufferContentAndReset(&buf); > + VIR_FREE(tmp); > + return NULL; > +} > + > + > +int > +virCPUDefFormatBuf(virConnectPtr conn, > + virBufferPtr buf, > + virCPUDefPtr def, > + const char *indent, > + int flags) > +{ > + unsigned int i; > + > + if (!def) > + return 0; > + > + if (indent == NULL) > + indent = ""; > + > + if (!def->model) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + "%s", _("Missing CPU model")); > + return -1; > + } > + > + if (!(flags & VIR_CPU_FORMAT_EMBEDED)) { > + if (def->type == VIR_CPU_TYPE_GUEST) { > + const char *match; > + if (!(match = virCPUMatchTypeToString(def->match))) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + _("Unexpected CPU match policy %d"), def->match); > + return -1; > + } > + > + virBufferVSprintf(buf, "%s<cpu match='%s'>\n", indent, match); > + } > + else > + virBufferVSprintf(buf, "%s<cpu>\n", indent); > + > + if (def->arch) > + virBufferVSprintf(buf, "%s <arch>%s</arch>\n", indent, def->arch); > + } > + > + virBufferVSprintf(buf, "%s <model>%s</model>\n", indent, def->model); > + > + if (def->sockets && def->cores && def->threads) { > + virBufferVSprintf(buf, "%s <topology", indent); > + virBufferVSprintf(buf, " sockets='%u'", def->sockets); > + virBufferVSprintf(buf, " cores='%u'", def->cores); > + virBufferVSprintf(buf, " threads='%u'", def->threads); > + virBufferAddLit(buf, "/>\n"); > + } > + > + for (i = 0 ; i < def->nfeatures ; i++) { > + virCPUFeatureDefPtr feature = def->features + i; > + > + if (!feature->name) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + "%s", _("Missing CPU feature name")); > + return -1; > + } > + > + if (def->type == VIR_CPU_TYPE_GUEST) { > + const char *policy; > + > + policy = virCPUFeaturePolicyTypeToString(feature->policy); > + if (!policy) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + _("Unexpected CPU feature policy %d"), feature->policy); > + return -1; > + } > + virBufferVSprintf(buf, "%s <feature policy='%s' name='%s'/>\n", > + indent, policy, feature->name); > + } > + else { > + virBufferVSprintf(buf, "%s <feature name='%s'/>\n", > + indent, feature->name); > + } > + } > + > + if (!(flags & VIR_CPU_FORMAT_EMBEDED)) > + virBufferVSprintf(buf, "%s</cpu>\n", indent); > + > + return 0; > +} > + > + > +int > +virCPUDefAddFeature(virConnectPtr conn, > + virCPUDefPtr def, > + const char *name, > + int policy) > +{ > + int i; > + > + for (i = 0 ; i < def->nfeatures ; i++) { > + if (STREQ(name, def->features[i].name)) { > + virCPUReportError(conn, VIR_ERR_INTERNAL_ERROR, > + _("CPU feature `%s' specified more than once"), name); > + return -1; > + } > + } > + > + if (VIR_REALLOC_N(def->features, def->nfeatures + 1) < 0) > + goto no_memory; > + > + if (def->type == VIR_CPU_TYPE_HOST) > + policy = -1; > + > + if (!(def->features[def->nfeatures].name = strdup(name))) > + goto no_memory; > + > + def->features[def->nfeatures].policy = policy; > + def->nfeatures++; > + > + return 0; > + > +no_memory: > + virReportOOMError(conn); > + return -1; > +} > diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h > new file mode 100644 > index 0000000..c71fbbb > --- /dev/null > +++ b/src/conf/cpu_conf.h > @@ -0,0 +1,116 @@ > +/* > + * cpu_conf.h: CPU XML handling > + * > + * Copyright (C) 2009 Red Hat, Inc. > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, write to the Free Software > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + * > + * Authors: > + * Jiri Denemark <jdenemar@xxxxxxxxxx> > + */ > + > +#ifndef __VIR_CPU_CONF_H__ > +#define __VIR_CPU_CONF_H__ > + > +#include "util.h" > +#include "buf.h" > +#include "xml.h" > + > + > +enum virCPUType { > + VIR_CPU_TYPE_HOST, > + VIR_CPU_TYPE_GUEST, > + VIR_CPU_TYPE_AUTO > +}; > + > +enum virCPUMatch { > + VIR_CPU_MATCH_MINIMUM, > + VIR_CPU_MATCH_EXACT, > + VIR_CPU_MATCH_STRICT, > + > + VIR_CPU_MATCH_LAST > +}; > + > +VIR_ENUM_DECL(virCPUMatch) > + > +enum virCPUFeaturePolicy { > + VIR_CPU_FEATURE_FORCE, > + VIR_CPU_FEATURE_REQUIRE, > + VIR_CPU_FEATURE_OPTIONAL, > + VIR_CPU_FEATURE_DISABLE, > + VIR_CPU_FEATURE_FORBID, > + > + VIR_CPU_FEATURE_LAST > +}; > + > +VIR_ENUM_DECL(virCPUFeaturePolicy) > + > +typedef struct _virCPUFeatureDef virCPUFeatureDef; > +typedef virCPUFeatureDef *virCPUFeatureDefPtr; > +struct _virCPUFeatureDef { > + char *name; > + int policy; /* enum virCPUFeaturePolicy */ > +}; > + > +typedef struct _virCPUDef virCPUDef; > +typedef virCPUDef *virCPUDefPtr; > +struct _virCPUDef { > + int type; /* enum virCPUType */ > + int match; /* enum virCPUMatch */ > + char *arch; > + char *model; > + unsigned int sockets; > + unsigned int cores; > + unsigned int threads; > + unsigned int nfeatures; > + virCPUFeatureDefPtr features; > +}; > + > + > +void > +virCPUDefFree(virCPUDefPtr def); > + > +virCPUDefPtr > +virCPUDefParseXML(virConnectPtr conn, > + const xmlNodePtr node, > + xmlXPathContextPtr ctxt, > + enum virCPUType mode); > + > +enum virCPUFormatFlags { > + VIR_CPU_FORMAT_EMBEDED = (1 << 0) /* embed into existing <cpu/> element > + * in host capabilities */ > +}; > + > + > +char * > +virCPUDefFormat(virConnectPtr conn, > + virCPUDefPtr def, > + const char *indent, > + int flags); > + > +int > +virCPUDefFormatBuf(virConnectPtr conn, > + virBufferPtr buf, > + virCPUDefPtr def, > + const char *indent, > + int flags); > + > +int > +virCPUDefAddFeature(virConnectPtr conn, > + virCPUDefPtr cpu, > + const char *name, > + int policy); > + > +#endif /* __VIR_CPU_CONF_H__ */ > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 5e94edf..0b4fe8b 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -601,6 +601,8 @@ void virDomainDefFree(virDomainDefPtr def) > > virSecurityLabelDefFree(def); > > + virCPUDefFree(def->cpu); > + > VIR_FREE(def); > } > > @@ -3360,6 +3362,16 @@ static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn, > if (virSecurityLabelDefParseXML(conn, def, ctxt, flags) == -1) > goto error; > > + if ((node = virXPathNode(conn, "./cpu[1]", ctxt)) != NULL) { > + xmlNodePtr oldnode = ctxt->node; > + ctxt->node = node; > + def->cpu = virCPUDefParseXML(conn, node, ctxt, VIR_CPU_TYPE_GUEST); > + ctxt->node = oldnode; > + > + if (def->cpu == NULL) > + goto error; > + } > + > return def; > > no_memory: > @@ -4660,6 +4672,9 @@ char *virDomainDefFormat(virConnectPtr conn, > virBufferAddLit(&buf, " </features>\n"); > } > > + if (virCPUDefFormatBuf(conn, &buf, def->cpu, " ", 0) < 0) > + goto cleanup; > + > virBufferVSprintf(&buf, " <clock offset='%s'/>\n", > def->localtime ? "localtime" : "utc"); > > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index ac39dcd..a807e9d 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -31,6 +31,7 @@ > #include "internal.h" > #include "capabilities.h" > #include "storage_encryption_conf.h" > +#include "cpu_conf.h" > #include "util.h" > #include "threads.h" > #include "hash.h" > @@ -635,6 +636,7 @@ struct _virDomainDef { > virDomainChrDefPtr console; > virSecurityLabelDef seclabel; > virDomainWatchdogDefPtr watchdog; > + virCPUDefPtr cpu; > }; > > /* Guest VM runtime state */ > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index e5ba365..9acd062 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -35,6 +35,7 @@ virCapabilitiesSetEmulatorRequired; > virCapabilitiesIsEmulatorRequired; > virCapabilitiesAllocMachines; > virCapabilitiesFreeMachines; > +virCapabilitiesSetHostCPU; > > > # conf.h > @@ -70,6 +71,14 @@ virCgroupGetFreezerState; > virCgroupSetFreezerState; > > > +# cpu_conf.h > +virCPUDefFree; > +virCPUDefParseXML; > +virCPUDefFormat; > +virCPUDefFormatBuf; > +virCPUDefAddFeature; > + > + > # datatypes.h > virGetDomain; > virGetInterface; > diff --git a/src/util/virterror.c b/src/util/virterror.c > index 3ff02ba..b1a96f8 100644 > --- a/src/util/virterror.c > +++ b/src/util/virterror.c > @@ -172,6 +172,9 @@ static const char *virErrorDomainName(virErrorDomain domain) { > case VIR_FROM_SECRET: > dom = "Secret Storage "; > break; > + case VIR_FROM_CPU: > + dom = "CPU "; > + break; > } > return(dom); > } ACK, I was wondering for a bit about the need for a new set of files, but it's a good idea to keep modules smaller, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list