[PATCH v2 10/21] Introduce virDomainDeviceDefParseXMLMany

Daniel Henrique Barboza danielhb413 at gmail.com
Thu Jan 30 16:44:22 UTC 2020


From: Shivaprasad G Bhat <sbhat at linux.vnet.ibm.com>

virDomainDeviceDefParseXMLMany will be used to parse '<devices>'
XML elements that will be used to supply multiple hostdevs
for hotplug/unplug. The idea is to parse each dev individually,
by calling the same code that already handles it today. The
result is returned in a new virDomainDeviceDefListPtr pointer
type, which is an array of device definitions.

This idea of calling existing functions to handles a single
device definition in a loop is the central idea of how PCI
multifunction hotplug and hotunplug is implemented in the
next patches. Roughly speaking, we'll use virDomainDeviceDefListPtr
lists to call (almost) the same hotplug/unplug mechanics we have
today for each hostdev in the list.

Signed-off-by: Shivaprasad G Bhat <sbhat at linux.vnet.ibm.com>
Signed-off-by: Daniel Henrique Barboza <danielhb413 at gmail.com>
---
 src/conf/domain_conf.c   | 171 +++++++++++++++++++++++++++++++++++----
 src/conf/domain_conf.h   |  32 ++++++++
 src/libvirt_private.syms |   5 ++
 3 files changed, 194 insertions(+), 14 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5b918cc737..887f7a2633 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1287,6 +1287,90 @@ virDomainXMLOptionDispose(void *obj)
         (xmlopt->config.privFree)(xmlopt->config.priv);
 }
 
+/* virDomainDeviceDefListAddCopy - add a *copy* of the device to this list */
+static int
+virDomainDeviceDefListAddCopy(virDomainDeviceDefListPtr list,
+                              virDomainDeviceDefPtr dev,
+                              virDomainDeviceDefListDataPtr data,
+                              void *parseOpaque)
+{
+    virDomainDeviceDefPtr copy = virDomainDeviceDefCopy(dev,
+                                                        data->def,
+                                                        data->xmlopt,
+                                                        parseOpaque);
+
+    if (!copy)
+        return -1;
+
+    if (VIR_APPEND_ELEMENT(list->devs, list->count, copy) < 0) {
+        virDomainDeviceDefFree(copy);
+        return -1;
+    }
+
+    return 0;
+}
+
+void virDomainDeviceDefListFree(virDomainDeviceDefListPtr list)
+{
+    size_t i;
+
+    if (!list)
+        return;
+    for (i = 0; i < list->count; i++)
+        virDomainDeviceDefFree(list->devs[i]);
+    VIR_FREE(list->devs);
+}
+
+void virDomainDeviceDefListFreeShallow(virDomainDeviceDefListPtr list)
+{
+    size_t i;
+
+    if (!list)
+        return;
+    for (i = 0; i < list->count; i++)
+        VIR_FREE(list->devs[i]);
+}
+
+
+/* virDomainDeviceDefListIter - Iterate through the list with the callback*/
+int
+virDomainDeviceDefListIterate(virDomainDeviceDefListPtr list,
+                              virDomainDeviceDefListIterCallback cb,
+                              void *data)
+{
+    size_t i;
+
+    for (i = 0; i < list->count; i++)
+        if (cb(list->devs[i], data))
+            return -1;
+
+    return 0;
+}
+
+virDomainDeviceDefListPtr
+virDomainDeviceDefListCopy(virDomainDeviceDefListPtr list,
+                           virDomainDeviceDefListDataPtr data,
+                           void *parseOpaque)
+{
+    size_t i;
+    virDomainDeviceDefListPtr devlist = NULL;
+
+    if (list && (VIR_ALLOC(devlist) < 0))
+        goto cleanup;
+
+    for (i = 0; i < list->count; i++) {
+        if (virDomainDeviceDefListAddCopy(devlist, list->devs[i],
+                                          data, parseOpaque) < 0)
+            goto cleanup;
+    }
+
+    return devlist;
+ cleanup:
+    virDomainDeviceDefListFree(devlist);
+    return NULL;
+}
+
+
 /**
  * virDomainKeyWrapCipherDefParseXML:
  *
@@ -16506,23 +16590,16 @@ virDomainVsockDefParseXML(virDomainXMLOptionPtr xmlopt,
     return g_steal_pointer(&vsock);
 }
 
-virDomainDeviceDefPtr
-virDomainDeviceDefParse(const char *xmlStr,
-                        const virDomainDef *def,
-                        virDomainXMLOptionPtr xmlopt,
-                        void *parseOpaque,
-                        unsigned int flags)
+static virDomainDeviceDefPtr
+virDomainDeviceDefParseXML(xmlNodePtr node,
+                           const virDomainDef *def,
+                           virDomainXMLOptionPtr xmlopt,
+                           xmlXPathContextPtr ctxt,
+                           void *parseOpaque,
+                           unsigned int flags)
 {
-    g_autoptr(xmlDoc) xml = NULL;
-    xmlNodePtr node;
-    g_autoptr(xmlXPathContext) ctxt = NULL;
     g_autofree virDomainDeviceDefPtr dev = NULL;
 
-    if (!(xml = virXMLParseStringCtxt(xmlStr, _("(device_definition)"), &ctxt)))
-        return NULL;
-
-    node = ctxt->node;
-
     if (VIR_ALLOC(dev) < 0)
         return NULL;
 
@@ -16678,6 +16755,32 @@ virDomainDeviceDefParse(const char *xmlStr,
 }
 
 
+virDomainDeviceDefPtr
+virDomainDeviceDefParse(const char *xmlStr,
+                        const virDomainDef *def,
+                        virDomainXMLOptionPtr xmlopt,
+                        void *parseOpaque,
+                        unsigned int flags)
+{
+    xmlDocPtr xml;
+    xmlNodePtr node;
+    xmlXPathContextPtr ctxt = NULL;
+    virDomainDeviceDefPtr dev = NULL;
+
+    if (!(xml = virXMLParseStringCtxt(xmlStr, _("(device_definition)"), &ctxt)))
+        return NULL;
+
+    node = ctxt->node;
+
+    dev = virDomainDeviceDefParseXML(node, def, xmlopt, ctxt, parseOpaque, flags);
+
+    xmlFreeDoc(xml);
+    xmlXPathFreeContext(ctxt);
+
+    return dev;
+ }
+
+
 virDomainDiskDefPtr
 virDomainDiskDefParse(const char *xmlStr,
                       virDomainXMLOptionPtr xmlopt,
@@ -31617,6 +31720,46 @@ virDomainDiskTranslateSourcePool(virDomainDiskDefPtr def)
     return 0;
 }
 
+virDomainDeviceDefListPtr
+virDomainDeviceDefParseXMLMany(const char *xml,
+                               const virDomainDef *def,
+                               virDomainXMLOptionPtr xmlopt,
+                               void *parseOpaque,
+                               unsigned int flags)
+{
+    xmlXPathContextPtr ctxt = NULL;
+    xmlDocPtr xmlPtr;
+    xmlNodePtr node, root;
+    virDomainDeviceDefPtr dev = NULL;
+    virDomainDeviceDefListPtr devlist;
+
+    if (!(xmlPtr = virXMLParseStringCtxt(xml, _("(device_definition)"), &ctxt)))
+        return NULL;
+
+    if (VIR_ALLOC(devlist) < 0)
+         goto exit;
+
+    root = xmlDocGetRootElement(xmlPtr);
+    node = root->children;
+    while (node) {
+        if (node->type == XML_ELEMENT_NODE) {
+            dev = virDomainDeviceDefParseXML(node, def, xmlopt, ctxt,
+                                             parseOpaque, flags);
+            if (VIR_APPEND_ELEMENT(devlist->devs, devlist->count, dev) < 0) {
+                virDomainDeviceDefFree(dev);
+                virDomainDeviceDefListFree(devlist);
+                goto exit;
+            }
+            dev = NULL;
+        }
+        node = node->next;
+    }
+
+ exit:
+    xmlFreeDoc(xmlPtr);
+    xmlXPathFreeContext(ctxt);
+    return devlist;
+}
 
 /**
  * virDomainDiskGetDetectZeroesMode:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 77a01fbec0..26d9ca6ba9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2648,6 +2648,33 @@ typedef enum {
 typedef int (*virDomainDefPostParseBasicCallback)(virDomainDefPtr def,
                                                   void *opaque);
 
+typedef struct _virDomainDeviceDefListData virDomainDeviceDefListData;
+typedef virDomainDeviceDefListData *virDomainDeviceDefListDataPtr;
+struct _virDomainDeviceDefListData {
+    const virDomainDef *def;
+    virDomainXMLOptionPtr xmlopt;
+};
+
+struct virDomainDeviceDefList {
+    virDomainDeviceDefPtr *devs;
+    size_t count;
+};
+typedef struct virDomainDeviceDefList *virDomainDeviceDefListPtr;
+
+typedef int (*virDomainDeviceDefListIterCallback)(virDomainDeviceDefPtr dev,
+                                                  void *opaque);
+int virDomainDeviceDefListIterate(virDomainDeviceDefListPtr devlist,
+                                  virDomainDeviceDefListIterCallback cb,
+                                  void *data);
+virDomainDeviceDefListPtr
+virDomainDeviceDefListCopy(virDomainDeviceDefListPtr list,
+                           virDomainDeviceDefListDataPtr data,
+                           void *parseOpaque);
+
+void virDomainDeviceDefListFree(virDomainDeviceDefListPtr list);
+void virDomainDeviceDefListFreeShallow(virDomainDeviceDefListPtr list);
+
+
 /* Called once after everything else has been parsed, for adjusting
  * overall domain defaults.
  * @parseOpaque is opaque data passed by virDomainDefParse* caller,
@@ -3053,6 +3080,11 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(const char *xmlStr,
                                               virDomainXMLOptionPtr xmlopt,
                                               void *parseOpaque,
                                               unsigned int flags);
+virDomainDeviceDefListPtr virDomainDeviceDefParseXMLMany(const char *xmlStr,
+                                                         const virDomainDef *def,
+                                                         virDomainXMLOptionPtr xmlopt,
+                                                         void *parseOpaque,
+                                                         unsigned int flags);
 virDomainDiskDefPtr virDomainDiskDefParse(const char *xmlStr,
                                           virDomainXMLOptionPtr xmlopt,
                                           unsigned int flags);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5b247ded4b..eda759c219 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -341,7 +341,12 @@ virDomainDeleteConfig;
 virDomainDeviceAliasIsUserAlias;
 virDomainDeviceDefCopy;
 virDomainDeviceDefFree;
+virDomainDeviceDefListCopy;
+virDomainDeviceDefListFree;
+virDomainDeviceDefListFreeShallow;
+virDomainDeviceDefListIterate;
 virDomainDeviceDefParse;
+virDomainDeviceDefParseXMLMany;
 virDomainDeviceFindSCSIController;
 virDomainDeviceGetInfo;
 virDomainDeviceInfoIterate;
-- 
2.24.1





More information about the libvir-list mailing list