render / rpms / libvirt

Forked from rpms/libvirt 9 months ago
Clone
c480ed
From 728231dcbbf2a4ab8a4bfe03fdf43d78bdeccbb0 Mon Sep 17 00:00:00 2001
c480ed
Message-Id: <728231dcbbf2a4ab8a4bfe03fdf43d78bdeccbb0@dist-git>
c480ed
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
c480ed
Date: Fri, 21 Jun 2019 09:24:46 +0200
c480ed
Subject: [PATCH] cpu: push more parsing logic into common code
c480ed
MIME-Version: 1.0
c480ed
Content-Type: text/plain; charset=UTF-8
c480ed
Content-Transfer-Encoding: 8bit
c480ed
c480ed
The x86 and ppc impls both duplicate some logic when parsing CPU
c480ed
features. Change the callback signature so that this duplication can be
c480ed
pushed up a level to common code.
c480ed
c480ed
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
c480ed
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
c480ed
(cherry picked from commit 0815f519784a7c565c543498777dc25f129620f9)
c480ed
c480ed
https://bugzilla.redhat.com/show_bug.cgi?id=1686895
c480ed
c480ed
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c480ed
Message-Id: <c770b678131dc5e207cbe84d276a2774e0c807c7.1561068591.git.jdenemar@redhat.com>
c480ed
Reviewed-by: Ján Tomko <jtomko@redhat.com>
c480ed
---
c480ed
 src/cpu/cpu_map.c   |  98 +++++++++++++---------
c480ed
 src/cpu/cpu_map.h   |  22 ++---
c480ed
 src/cpu/cpu_ppc64.c | 112 ++++++-------------------
c480ed
 src/cpu/cpu_x86.c   | 196 +++++++++++++-------------------------------
c480ed
 4 files changed, 143 insertions(+), 285 deletions(-)
c480ed
c480ed
diff --git a/src/cpu/cpu_map.c b/src/cpu/cpu_map.c
c480ed
index 333c7ef24f..ac7e58037a 100644
c480ed
--- a/src/cpu/cpu_map.c
c480ed
+++ b/src/cpu/cpu_map.c
c480ed
@@ -35,31 +35,47 @@
c480ed
 
c480ed
 VIR_LOG_INIT("cpu.cpu_map");
c480ed
 
c480ed
-VIR_ENUM_IMPL(cpuMapElement, CPU_MAP_ELEMENT_LAST,
c480ed
-    "vendor",
c480ed
-    "feature",
c480ed
-    "model")
c480ed
-
c480ed
-
c480ed
-static int load(xmlXPathContextPtr ctxt,
c480ed
-                cpuMapElement element,
c480ed
-                cpuMapLoadCallback callback,
c480ed
-                void *data)
c480ed
+static int
c480ed
+loadData(const char *mapfile,
c480ed
+         xmlXPathContextPtr ctxt,
c480ed
+         const char *element,
c480ed
+         cpuMapLoadCallback callback,
c480ed
+         void *data)
c480ed
 {
c480ed
     int ret = -1;
c480ed
     xmlNodePtr ctxt_node;
c480ed
     xmlNodePtr *nodes = NULL;
c480ed
     int n;
c480ed
+    size_t i;
c480ed
+    int rv;
c480ed
 
c480ed
     ctxt_node = ctxt->node;
c480ed
 
c480ed
-    n = virXPathNodeSet(cpuMapElementTypeToString(element), ctxt, &nodes);
c480ed
-    if (n < 0)
c480ed
+    if ((n = virXPathNodeSet(element, ctxt, &nodes)) < 0)
c480ed
         goto cleanup;
c480ed
 
c480ed
-    if (n > 0 &&
c480ed
-        callback(element, ctxt, nodes, n, data) < 0)
c480ed
+    if (n > 0 && !callback) {
c480ed
+        virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
+                       _("Unexpected element '%s' in CPU map '%s'"), element, mapfile);
c480ed
         goto cleanup;
c480ed
+    }
c480ed
+
c480ed
+    for (i = 0; i < n; i++) {
c480ed
+        xmlNodePtr old = ctxt->node;
c480ed
+        char *name = virXMLPropString(nodes[i], "name");
c480ed
+        if (!name) {
c480ed
+            virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
+                           _("cannot find %s name in CPU map '%s'"), element, mapfile);
c480ed
+            goto cleanup;
c480ed
+        }
c480ed
+        VIR_DEBUG("Load %s name %s", element, name);
c480ed
+        ctxt->node = nodes[i];
c480ed
+        rv = callback(ctxt, name, data);
c480ed
+        ctxt->node = old;
c480ed
+        VIR_FREE(name);
c480ed
+        if (rv < 0)
c480ed
+            goto cleanup;
c480ed
+    }
c480ed
 
c480ed
     ret = 0;
c480ed
 
c480ed
@@ -72,13 +88,14 @@ static int load(xmlXPathContextPtr ctxt,
c480ed
 
c480ed
 static int
c480ed
 cpuMapLoadInclude(const char *filename,
c480ed
-                  cpuMapLoadCallback cb,
c480ed
+                  cpuMapLoadCallback vendorCB,
c480ed
+                  cpuMapLoadCallback featureCB,
c480ed
+                  cpuMapLoadCallback modelCB,
c480ed
                   void *data)
c480ed
 {
c480ed
     xmlDocPtr xml = NULL;
c480ed
     xmlXPathContextPtr ctxt = NULL;
c480ed
     int ret = -1;
c480ed
-    int element;
c480ed
     char *mapfile;
c480ed
 
c480ed
     if (!(mapfile = virFileFindResource(filename,
c480ed
@@ -93,13 +110,14 @@ cpuMapLoadInclude(const char *filename,
c480ed
 
c480ed
     ctxt->node = xmlDocGetRootElement(xml);
c480ed
 
c480ed
-    for (element = 0; element < CPU_MAP_ELEMENT_LAST; element++) {
c480ed
-        if (load(ctxt, element, cb, data) < 0) {
c480ed
-            virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
-                           _("cannot parse CPU map '%s'"), mapfile);
c480ed
-            goto cleanup;
c480ed
-        }
c480ed
-    }
c480ed
+    if (loadData(mapfile, ctxt, "vendor", vendorCB, data) < 0)
c480ed
+        goto cleanup;
c480ed
+
c480ed
+    if (loadData(mapfile, ctxt, "feature", featureCB, data) < 0)
c480ed
+        goto cleanup;
c480ed
+
c480ed
+    if (loadData(mapfile, ctxt, "model", modelCB, data) < 0)
c480ed
+        goto cleanup;
c480ed
 
c480ed
     ret = 0;
c480ed
 
c480ed
@@ -114,7 +132,9 @@ cpuMapLoadInclude(const char *filename,
c480ed
 
c480ed
 static int
c480ed
 loadIncludes(xmlXPathContextPtr ctxt,
c480ed
-             cpuMapLoadCallback callback,
c480ed
+             cpuMapLoadCallback vendorCB,
c480ed
+             cpuMapLoadCallback featureCB,
c480ed
+             cpuMapLoadCallback modelCB,
c480ed
              void *data)
c480ed
 {
c480ed
     int ret = -1;
c480ed
@@ -137,7 +157,7 @@ loadIncludes(xmlXPathContextPtr ctxt,
c480ed
             goto cleanup;
c480ed
         }
c480ed
         VIR_DEBUG("Finding CPU map include '%s'", filename);
c480ed
-        if (cpuMapLoadInclude(filename, callback, data) < 0) {
c480ed
+        if (cpuMapLoadInclude(filename, vendorCB, featureCB, modelCB, data) < 0) {
c480ed
             VIR_FREE(filename);
c480ed
             goto cleanup;
c480ed
         }
c480ed
@@ -155,7 +175,9 @@ loadIncludes(xmlXPathContextPtr ctxt,
c480ed
 
c480ed
 
c480ed
 int cpuMapLoad(const char *arch,
c480ed
-               cpuMapLoadCallback cb,
c480ed
+               cpuMapLoadCallback vendorCB,
c480ed
+               cpuMapLoadCallback featureCB,
c480ed
+               cpuMapLoadCallback modelCB,
c480ed
                void *data)
c480ed
 {
c480ed
     xmlDocPtr xml = NULL;
c480ed
@@ -163,7 +185,6 @@ int cpuMapLoad(const char *arch,
c480ed
     virBuffer buf = VIR_BUFFER_INITIALIZER;
c480ed
     char *xpath = NULL;
c480ed
     int ret = -1;
c480ed
-    int element;
c480ed
     char *mapfile;
c480ed
 
c480ed
     if (!(mapfile = virFileFindResource("cpu_map.xml",
c480ed
@@ -179,12 +200,6 @@ int cpuMapLoad(const char *arch,
c480ed
         goto cleanup;
c480ed
     }
c480ed
 
c480ed
-    if (cb == NULL) {
c480ed
-        virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
-                       "%s", _("no callback provided"));
c480ed
-        goto cleanup;
c480ed
-    }
c480ed
-
c480ed
     if (!(xml = virXMLParseFileCtxt(mapfile, &ctxt)))
c480ed
         goto cleanup;
c480ed
 
c480ed
@@ -202,15 +217,16 @@ int cpuMapLoad(const char *arch,
c480ed
         goto cleanup;
c480ed
     }
c480ed
 
c480ed
-    for (element = 0; element < CPU_MAP_ELEMENT_LAST; element++) {
c480ed
-        if (load(ctxt, element, cb, data) < 0) {
c480ed
-            virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
-                           _("cannot parse CPU map '%s'"), mapfile);
c480ed
-            goto cleanup;
c480ed
-        }
c480ed
-    }
c480ed
+    if (loadData(mapfile, ctxt, "vendor", vendorCB, data) < 0)
c480ed
+        goto cleanup;
c480ed
 
c480ed
-    if (loadIncludes(ctxt, cb, data) < 0)
c480ed
+    if (loadData(mapfile, ctxt, "feature", featureCB, data) < 0)
c480ed
+        goto cleanup;
c480ed
+
c480ed
+    if (loadData(mapfile, ctxt, "model", modelCB, data) < 0)
c480ed
+        goto cleanup;
c480ed
+
c480ed
+    if (loadIncludes(ctxt, vendorCB, featureCB, modelCB, data) < 0)
c480ed
         goto cleanup;
c480ed
 
c480ed
     ret = 0;
c480ed
diff --git a/src/cpu/cpu_map.h b/src/cpu/cpu_map.h
c480ed
index 0c7507e98f..4596987150 100644
c480ed
--- a/src/cpu/cpu_map.h
c480ed
+++ b/src/cpu/cpu_map.h
c480ed
@@ -26,28 +26,16 @@
c480ed
 
c480ed
 # include "virxml.h"
c480ed
 
c480ed
-
c480ed
-typedef enum {
c480ed
-    CPU_MAP_ELEMENT_VENDOR,
c480ed
-    CPU_MAP_ELEMENT_FEATURE,
c480ed
-    CPU_MAP_ELEMENT_MODEL,
c480ed
-
c480ed
-    CPU_MAP_ELEMENT_LAST
c480ed
-} cpuMapElement;
c480ed
-
c480ed
-VIR_ENUM_DECL(cpuMapElement)
c480ed
-
c480ed
-
c480ed
 typedef int
c480ed
-(*cpuMapLoadCallback)  (cpuMapElement element,
c480ed
-                        xmlXPathContextPtr ctxt,
c480ed
-                        xmlNodePtr *nodes,
c480ed
-                        int n,
c480ed
+(*cpuMapLoadCallback)  (xmlXPathContextPtr ctxt,
c480ed
+                        const char *name,
c480ed
                         void *data);
c480ed
 
c480ed
 int
c480ed
 cpuMapLoad(const char *arch,
c480ed
-           cpuMapLoadCallback cb,
c480ed
+           cpuMapLoadCallback vendorCB,
c480ed
+           cpuMapLoadCallback featureCB,
c480ed
+           cpuMapLoadCallback modelCB,
c480ed
            void *data);
c480ed
 
c480ed
 #endif /* __VIR_CPU_MAP_H__ */
c480ed
diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c
c480ed
index d562677fa3..75da5b77d8 100644
c480ed
--- a/src/cpu/cpu_ppc64.c
c480ed
+++ b/src/cpu/cpu_ppc64.c
c480ed
@@ -281,21 +281,19 @@ ppc64MapFree(struct ppc64_map *map)
c480ed
     VIR_FREE(map);
c480ed
 }
c480ed
 
c480ed
-static struct ppc64_vendor *
c480ed
-ppc64VendorParse(xmlXPathContextPtr ctxt,
c480ed
-                 struct ppc64_map *map)
c480ed
+static int
c480ed
+ppc64VendorParse(xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
c480ed
+                 const char *name,
c480ed
+                 void *data)
c480ed
 {
c480ed
+    struct ppc64_map *map = data;
c480ed
     struct ppc64_vendor *vendor;
c480ed
 
c480ed
     if (VIR_ALLOC(vendor) < 0)
c480ed
-        return NULL;
c480ed
+        return -1;
c480ed
 
c480ed
-    vendor->name = virXPathString("string(@name)", ctxt);
c480ed
-    if (!vendor->name) {
c480ed
-        virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
-                       "%s", _("Missing CPU vendor name"));
c480ed
+    if (VIR_STRDUP(vendor->name, name) < 0)
c480ed
         goto error;
c480ed
-    }
c480ed
 
c480ed
     if (ppc64VendorFind(map, vendor->name)) {
c480ed
         virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
@@ -303,57 +301,36 @@ ppc64VendorParse(xmlXPathContextPtr ctxt,
c480ed
         goto error;
c480ed
     }
c480ed
 
c480ed
-    return vendor;
c480ed
+    if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0)
c480ed
+        goto error;
c480ed
+
c480ed
+    return 0;
c480ed
 
c480ed
  error:
c480ed
     ppc64VendorFree(vendor);
c480ed
-    return NULL;
c480ed
+    return -1;
c480ed
 }
c480ed
 
c480ed
 
c480ed
 static int
c480ed
-ppc64VendorsLoad(struct ppc64_map *map,
c480ed
-                 xmlXPathContextPtr ctxt,
c480ed
-                 xmlNodePtr *nodes,
c480ed
-                 int n)
c480ed
-{
c480ed
-    struct ppc64_vendor *vendor;
c480ed
-    size_t i;
c480ed
-
c480ed
-    if (VIR_ALLOC_N(map->vendors, n) < 0)
c480ed
-        return -1;
c480ed
-
c480ed
-    for (i = 0; i < n; i++) {
c480ed
-        ctxt->node = nodes[i];
c480ed
-        if (!(vendor = ppc64VendorParse(ctxt, map)))
c480ed
-            return -1;
c480ed
-        map->vendors[map->nvendors++] = vendor;
c480ed
-    }
c480ed
-
c480ed
-    return 0;
c480ed
-}
c480ed
-
c480ed
-
c480ed
-static struct ppc64_model *
c480ed
 ppc64ModelParse(xmlXPathContextPtr ctxt,
c480ed
-                struct ppc64_map *map)
c480ed
+                const char *name,
c480ed
+                void *data)
c480ed
 {
c480ed
+    struct ppc64_map *map = data;
c480ed
     struct ppc64_model *model;
c480ed
     xmlNodePtr *nodes = NULL;
c480ed
     char *vendor = NULL;
c480ed
     unsigned long pvr;
c480ed
     size_t i;
c480ed
     int n;
c480ed
+    int ret = -1;
c480ed
 
c480ed
     if (VIR_ALLOC(model) < 0)
c480ed
         goto error;
c480ed
 
c480ed
-    model->name = virXPathString("string(@name)", ctxt);
c480ed
-    if (!model->name) {
c480ed
-        virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
-                       "%s", _("Missing CPU model name"));
c480ed
+    if (VIR_STRDUP(model->name, name) < 0)
c480ed
         goto error;
c480ed
-    }
c480ed
 
c480ed
     if (ppc64ModelFind(map, model->name)) {
c480ed
         virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
@@ -410,63 +387,22 @@ ppc64ModelParse(xmlXPathContextPtr ctxt,
c480ed
         model->data.pvr[i].mask = pvr;
c480ed
     }
c480ed
 
c480ed
+    if (VIR_APPEND_ELEMENT(map->models, map->nmodels, model) < 0)
c480ed
+        goto error;
c480ed
+
c480ed
+    ret = 0;
c480ed
+
c480ed
  cleanup:
c480ed
     VIR_FREE(vendor);
c480ed
     VIR_FREE(nodes);
c480ed
-    return model;
c480ed
+    return ret;
c480ed
 
c480ed
  error:
c480ed
     ppc64ModelFree(model);
c480ed
-    model = NULL;
c480ed
     goto cleanup;
c480ed
 }
c480ed
 
c480ed
 
c480ed
-static int
c480ed
-ppc64ModelsLoad(struct ppc64_map *map,
c480ed
-                xmlXPathContextPtr ctxt,
c480ed
-                xmlNodePtr *nodes,
c480ed
-                int n)
c480ed
-{
c480ed
-    struct ppc64_model *model;
c480ed
-    size_t i;
c480ed
-
c480ed
-    if (VIR_ALLOC_N(map->models, n) < 0)
c480ed
-        return -1;
c480ed
-
c480ed
-    for (i = 0; i < n; i++) {
c480ed
-        ctxt->node = nodes[i];
c480ed
-        if (!(model = ppc64ModelParse(ctxt, map)))
c480ed
-            return -1;
c480ed
-        map->models[map->nmodels++] = model;
c480ed
-    }
c480ed
-
c480ed
-    return 0;
c480ed
-}
c480ed
-
c480ed
-
c480ed
-static int
c480ed
-ppc64MapLoadCallback(cpuMapElement element,
c480ed
-                     xmlXPathContextPtr ctxt,
c480ed
-                     xmlNodePtr *nodes,
c480ed
-                     int n,
c480ed
-                     void *data)
c480ed
-{
c480ed
-    struct ppc64_map *map = data;
c480ed
-
c480ed
-    switch (element) {
c480ed
-    case CPU_MAP_ELEMENT_VENDOR:
c480ed
-        return ppc64VendorsLoad(map, ctxt, nodes, n);
c480ed
-    case CPU_MAP_ELEMENT_MODEL:
c480ed
-        return ppc64ModelsLoad(map, ctxt, nodes, n);
c480ed
-    case CPU_MAP_ELEMENT_FEATURE:
c480ed
-    case CPU_MAP_ELEMENT_LAST:
c480ed
-        break;
c480ed
-    }
c480ed
-
c480ed
-    return 0;
c480ed
-}
c480ed
-
c480ed
 static struct ppc64_map *
c480ed
 ppc64LoadMap(void)
c480ed
 {
c480ed
@@ -475,7 +411,7 @@ ppc64LoadMap(void)
c480ed
     if (VIR_ALLOC(map) < 0)
c480ed
         goto error;
c480ed
 
c480ed
-    if (cpuMapLoad("ppc64", ppc64MapLoadCallback, map) < 0)
c480ed
+    if (cpuMapLoad("ppc64", ppc64VendorParse, NULL, ppc64ModelParse, map) < 0)
c480ed
         goto error;
c480ed
 
c480ed
     return map;
c480ed
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
c480ed
index 124aa5fd5e..11dbd1e757 100644
c480ed
--- a/src/cpu/cpu_x86.c
c480ed
+++ b/src/cpu/cpu_x86.c
c480ed
@@ -720,22 +720,21 @@ x86VendorFind(virCPUx86MapPtr map,
c480ed
 }
c480ed
 
c480ed
 
c480ed
-static virCPUx86VendorPtr
c480ed
+static int
c480ed
 x86VendorParse(xmlXPathContextPtr ctxt,
c480ed
-               virCPUx86MapPtr map)
c480ed
+               const char *name,
c480ed
+               void *data)
c480ed
 {
c480ed
+    virCPUx86MapPtr map = data;
c480ed
     virCPUx86VendorPtr vendor = NULL;
c480ed
     char *string = NULL;
c480ed
+    int ret = -1;
c480ed
 
c480ed
     if (VIR_ALLOC(vendor) < 0)
c480ed
         goto error;
c480ed
 
c480ed
-    vendor->name = virXPathString("string(@name)", ctxt);
c480ed
-    if (!vendor->name) {
c480ed
-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
c480ed
-                       _("Missing CPU vendor name"));
c480ed
+    if (VIR_STRDUP(vendor->name, name) < 0)
c480ed
         goto error;
c480ed
-    }
c480ed
 
c480ed
     if (x86VendorFind(map, vendor->name)) {
c480ed
         virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
@@ -754,40 +753,21 @@ x86VendorParse(xmlXPathContextPtr ctxt,
c480ed
     if (virCPUx86VendorToCPUID(string, &vendor->cpuid) < 0)
c480ed
         goto error;
c480ed
 
c480ed
+    if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0)
c480ed
+        goto error;
c480ed
+
c480ed
+    ret = 0;
c480ed
+
c480ed
  cleanup:
c480ed
     VIR_FREE(string);
c480ed
-    return vendor;
c480ed
+    return ret;
c480ed
 
c480ed
  error:
c480ed
     x86VendorFree(vendor);
c480ed
-    vendor = NULL;
c480ed
     goto cleanup;
c480ed
 }
c480ed
 
c480ed
 
c480ed
-static int
c480ed
-x86VendorsLoad(virCPUx86MapPtr map,
c480ed
-               xmlXPathContextPtr ctxt,
c480ed
-               xmlNodePtr *nodes,
c480ed
-               int n)
c480ed
-{
c480ed
-    virCPUx86VendorPtr vendor;
c480ed
-    size_t i;
c480ed
-
c480ed
-    if (VIR_ALLOC_N(map->vendors, n) < 0)
c480ed
-        return -1;
c480ed
-
c480ed
-    for (i = 0; i < n; i++) {
c480ed
-        ctxt->node = nodes[i];
c480ed
-        if (!(vendor = x86VendorParse(ctxt, map)))
c480ed
-            return -1;
c480ed
-        map->vendors[map->nvendors++] = vendor;
c480ed
-    }
c480ed
-
c480ed
-    return 0;
c480ed
-}
c480ed
-
c480ed
-
c480ed
 static virCPUx86FeaturePtr
c480ed
 x86FeatureNew(void)
c480ed
 {
c480ed
@@ -909,27 +889,27 @@ x86ParseCPUID(xmlXPathContextPtr ctxt,
c480ed
 }
c480ed
 
c480ed
 
c480ed
-static virCPUx86FeaturePtr
c480ed
+static int
c480ed
 x86FeatureParse(xmlXPathContextPtr ctxt,
c480ed
-                virCPUx86MapPtr map)
c480ed
+                const char *name,
c480ed
+                void *data)
c480ed
 {
c480ed
+    virCPUx86MapPtr map = data;
c480ed
     xmlNodePtr *nodes = NULL;
c480ed
     virCPUx86FeaturePtr feature;
c480ed
     virCPUx86CPUID cpuid;
c480ed
     size_t i;
c480ed
     int n;
c480ed
     char *str = NULL;
c480ed
+    int ret = -1;
c480ed
 
c480ed
     if (!(feature = x86FeatureNew()))
c480ed
         goto error;
c480ed
 
c480ed
     feature->migratable = true;
c480ed
-    feature->name = virXPathString("string(@name)", ctxt);
c480ed
-    if (!feature->name) {
c480ed
-        virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
-                       "%s", _("Missing CPU feature name"));
c480ed
+
c480ed
+    if (VIR_STRDUP(feature->name, name) < 0)
c480ed
         goto error;
c480ed
-    }
c480ed
 
c480ed
     if (x86FeatureFind(map, feature->name)) {
c480ed
         virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
@@ -957,46 +937,28 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
c480ed
             goto error;
c480ed
     }
c480ed
 
c480ed
+    if (!feature->migratable &&
c480ed
+        VIR_APPEND_ELEMENT_COPY(map->migrate_blockers,
c480ed
+                                map->nblockers,
c480ed
+                                feature) < 0)
c480ed
+        goto error;
c480ed
+
c480ed
+    if (VIR_APPEND_ELEMENT(map->features, map->nfeatures, feature) < 0)
c480ed
+        goto error;
c480ed
+
c480ed
+    ret = 0;
c480ed
+
c480ed
  cleanup:
c480ed
     VIR_FREE(nodes);
c480ed
     VIR_FREE(str);
c480ed
-    return feature;
c480ed
+    return ret;
c480ed
 
c480ed
  error:
c480ed
     x86FeatureFree(feature);
c480ed
-    feature = NULL;
c480ed
     goto cleanup;
c480ed
 }
c480ed
 
c480ed
 
c480ed
-static int
c480ed
-x86FeaturesLoad(virCPUx86MapPtr map,
c480ed
-                xmlXPathContextPtr ctxt,
c480ed
-                xmlNodePtr *nodes,
c480ed
-                int n)
c480ed
-{
c480ed
-    virCPUx86FeaturePtr feature;
c480ed
-    size_t i;
c480ed
-
c480ed
-    if (VIR_ALLOC_N(map->features, n) < 0)
c480ed
-        return -1;
c480ed
-
c480ed
-    for (i = 0; i < n; i++) {
c480ed
-        ctxt->node = nodes[i];
c480ed
-        if (!(feature = x86FeatureParse(ctxt, map)))
c480ed
-            return -1;
c480ed
-        map->features[map->nfeatures++] = feature;
c480ed
-        if (!feature->migratable &&
c480ed
-            VIR_APPEND_ELEMENT(map->migrate_blockers,
c480ed
-                               map->nblockers,
c480ed
-                               feature) < 0)
c480ed
-            return -1;
c480ed
-    }
c480ed
-
c480ed
-    return 0;
c480ed
-}
c480ed
-
c480ed
-
c480ed
 static virCPUx86ModelPtr
c480ed
 x86ModelNew(void)
c480ed
 {
c480ed
@@ -1192,47 +1154,46 @@ x86ModelCompare(virCPUx86ModelPtr model1,
c480ed
 }
c480ed
 
c480ed
 
c480ed
-static virCPUx86ModelPtr
c480ed
+static int
c480ed
 x86ModelParse(xmlXPathContextPtr ctxt,
c480ed
-              virCPUx86MapPtr map)
c480ed
+              const char *name,
c480ed
+              void *data)
c480ed
 {
c480ed
+    virCPUx86MapPtr map = data;
c480ed
     xmlNodePtr *nodes = NULL;
c480ed
     virCPUx86ModelPtr model;
c480ed
     char *vendor = NULL;
c480ed
     size_t i;
c480ed
     int n;
c480ed
+    int ret = -1;
c480ed
 
c480ed
     if (!(model = x86ModelNew()))
c480ed
         goto error;
c480ed
 
c480ed
-    model->name = virXPathString("string(@name)", ctxt);
c480ed
-    if (!model->name) {
c480ed
-        virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
-                       "%s", _("Missing CPU model name"));
c480ed
+    if (VIR_STRDUP(model->name, name) < 0)
c480ed
         goto error;
c480ed
-    }
c480ed
 
c480ed
     if (virXPathNode("./model", ctxt)) {
c480ed
         virCPUx86ModelPtr ancestor;
c480ed
-        char *name;
c480ed
+        char *anname;
c480ed
 
c480ed
-        name = virXPathString("string(./model/@name)", ctxt);
c480ed
-        if (!name) {
c480ed
+        anname = virXPathString("string(./model/@name)", ctxt);
c480ed
+        if (!anname) {
c480ed
             virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
                            _("Missing ancestor's name in CPU model %s"),
c480ed
                            model->name);
c480ed
             goto error;
c480ed
         }
c480ed
 
c480ed
-        if (!(ancestor = x86ModelFind(map, name))) {
c480ed
+        if (!(ancestor = x86ModelFind(map, anname))) {
c480ed
             virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
                            _("Ancestor model %s not found for CPU model %s"),
c480ed
-                           name, model->name);
c480ed
-            VIR_FREE(name);
c480ed
+                           anname, model->name);
c480ed
+            VIR_FREE(anname);
c480ed
             goto error;
c480ed
         }
c480ed
 
c480ed
-        VIR_FREE(name);
c480ed
+        VIR_FREE(anname);
c480ed
 
c480ed
         model->vendor = ancestor->vendor;
c480ed
         model->signature = ancestor->signature;
c480ed
@@ -1287,62 +1248,43 @@ x86ModelParse(xmlXPathContextPtr ctxt,
c480ed
 
c480ed
     for (i = 0; i < n; i++) {
c480ed
         virCPUx86FeaturePtr feature;
c480ed
-        char *name;
c480ed
+        char *ftname;
c480ed
 
c480ed
-        if (!(name = virXMLPropString(nodes[i], "name"))) {
c480ed
+        if (!(ftname = virXMLPropString(nodes[i], "name"))) {
c480ed
             virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
                            _("Missing feature name for CPU model %s"), model->name);
c480ed
             goto error;
c480ed
         }
c480ed
 
c480ed
-        if (!(feature = x86FeatureFind(map, name))) {
c480ed
+        if (!(feature = x86FeatureFind(map, ftname))) {
c480ed
             virReportError(VIR_ERR_INTERNAL_ERROR,
c480ed
                            _("Feature %s required by CPU model %s not found"),
c480ed
-                           name, model->name);
c480ed
-            VIR_FREE(name);
c480ed
+                           ftname, model->name);
c480ed
+            VIR_FREE(ftname);
c480ed
             goto error;
c480ed
         }
c480ed
-        VIR_FREE(name);
c480ed
+        VIR_FREE(ftname);
c480ed
 
c480ed
         if (x86DataAdd(&model->data, &feature->data))
c480ed
             goto error;
c480ed
     }
c480ed
 
c480ed
+    if (VIR_APPEND_ELEMENT(map->models, map->nmodels, model) < 0)
c480ed
+        goto error;
c480ed
+
c480ed
+    ret = 0;
c480ed
+
c480ed
  cleanup:
c480ed
     VIR_FREE(vendor);
c480ed
     VIR_FREE(nodes);
c480ed
-    return model;
c480ed
+    return ret;
c480ed
 
c480ed
  error:
c480ed
     x86ModelFree(model);
c480ed
-    model = NULL;
c480ed
     goto cleanup;
c480ed
 }
c480ed
 
c480ed
 
c480ed
-static int
c480ed
-x86ModelsLoad(virCPUx86MapPtr map,
c480ed
-              xmlXPathContextPtr ctxt,
c480ed
-              xmlNodePtr *nodes,
c480ed
-              int n)
c480ed
-{
c480ed
-    virCPUx86ModelPtr model;
c480ed
-    size_t i;
c480ed
-
c480ed
-    if (VIR_ALLOC_N(map->models, n) < 0)
c480ed
-        return -1;
c480ed
-
c480ed
-    for (i = 0; i < n; i++) {
c480ed
-        ctxt->node = nodes[i];
c480ed
-        if (!(model = x86ModelParse(ctxt, map)))
c480ed
-            return -1;
c480ed
-        map->models[map->nmodels++] = model;
c480ed
-    }
c480ed
-
c480ed
-    return 0;
c480ed
-}
c480ed
-
c480ed
-
c480ed
 static void
c480ed
 x86MapFree(virCPUx86MapPtr map)
c480ed
 {
c480ed
@@ -1372,30 +1314,6 @@ x86MapFree(virCPUx86MapPtr map)
c480ed
 }
c480ed
 
c480ed
 
c480ed
-static int
c480ed
-x86MapLoadCallback(cpuMapElement element,
c480ed
-                   xmlXPathContextPtr ctxt,
c480ed
-                   xmlNodePtr *nodes,
c480ed
-                   int n,
c480ed
-                   void *data)
c480ed
-{
c480ed
-    virCPUx86MapPtr map = data;
c480ed
-
c480ed
-    switch (element) {
c480ed
-    case CPU_MAP_ELEMENT_VENDOR:
c480ed
-        return x86VendorsLoad(map, ctxt, nodes, n);
c480ed
-    case CPU_MAP_ELEMENT_FEATURE:
c480ed
-        return x86FeaturesLoad(map, ctxt, nodes, n);
c480ed
-    case CPU_MAP_ELEMENT_MODEL:
c480ed
-        return x86ModelsLoad(map, ctxt, nodes, n);
c480ed
-    case CPU_MAP_ELEMENT_LAST:
c480ed
-        break;
c480ed
-    }
c480ed
-
c480ed
-    return 0;
c480ed
-}
c480ed
-
c480ed
-
c480ed
 static virCPUx86MapPtr
c480ed
 virCPUx86LoadMap(void)
c480ed
 {
c480ed
@@ -1404,7 +1322,7 @@ virCPUx86LoadMap(void)
c480ed
     if (VIR_ALLOC(map) < 0)
c480ed
         return NULL;
c480ed
 
c480ed
-    if (cpuMapLoad("x86", x86MapLoadCallback, map) < 0)
c480ed
+    if (cpuMapLoad("x86", x86VendorParse, x86FeatureParse, x86ModelParse, map) < 0)
c480ed
         goto error;
c480ed
 
c480ed
     return map;
c480ed
-- 
c480ed
2.22.0
c480ed