<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Thu, May 19, 2016 at 3:01 AM, Shivaprasad G Bhat <span dir="ltr"><<a href="mailto:shivaprasadbhat@gmail.com" target="_blank">shivaprasadbhat@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This patch just introduces the parser function used by<br>
the later patches. The parser disallows hostdevices to be<br>
used with other virtio devices simultaneously.<br>
<br>
Signed-off-by: Shivaprasad G Bhat <<a href="mailto:sbhat@linux.vnet.ibm.com">sbhat@linux.vnet.ibm.com</a>><br>
---<br>
 src/conf/domain_conf.c   |  236 ++++++++++++++++++++++++++++++++++++++++++++++<br>
 src/conf/domain_conf.h   |   22 ++++<br>
 src/libvirt_private.syms |    3 +<br>
 3 files changed, 261 insertions(+)<br>
<br>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c<br>
index ed0c471..e946147 100644<br>
--- a/src/conf/domain_conf.c<br>
+++ b/src/conf/domain_conf.c<br>
@@ -860,6 +860,36 @@ virDomainXMLOptionClassDispose(void *obj)<br>
         (xmlopt->config.privFree)(xmlopt->config.priv);<br>
 }<br>
<br>
+/* virDomainDeviceDefListAddCopy - add a *copy* of the device to this list */<br>
+int<br>
+virDomainDeviceDefListAddCopy(virDomainDeviceDefListPtr list,<br>
+                              virDomainDeviceDefPtr dev,<br>
+                              const virDomainDef *def,<br>
+                              virCapsPtr caps,<br>
+                              virDomainXMLOptionPtr xmlopt)<br>
+{<br>
+    virDomainDeviceDefPtr copy = virDomainDeviceDefCopy(dev, def, caps, xmlopt);<br>
+<br>
+    if (!copy)<br>
+        return -1;<br>
+    if (VIR_APPEND_ELEMENT(list->devs, list->count, copy) < 0) {<br>
+        virDomainDeviceDefFree(copy);<br>
+        return -1;<br>
+    }<br>
+    return 0;<br>
+}<br>
+<br>
+void virDomainDeviceDefListDispose(virDomainDeviceDefListPtr list)<br>
+{<br>
+    size_t i;<br>
+<br>
+    if (!list)<br>
+        return;<br>
+    for (i = 0; i < list->count; i++)<br>
+        virDomainDeviceDefFree(list->devs[i]);<br>
+    VIR_FREE(list);<br>
+}<br>
+<br>
 /**<br>
  * virDomainKeyWrapCipherDefParseXML:<br>
  *<br>
@@ -24365,3 +24395,209 @@ virDomainObjGetShortName(virDomainObjPtr vm)<br>
<br>
     return ret;<br>
 }<br>
+<br>
+static int<br>
+virDomainPCIMultifunctionDeviceDefParseXML(xmlXPathContextPtr ctxt,<br>
+                                           const virDomainDef *def,<br>
+                                           virDomainDeviceDefListPtr devlist,<br>
+                                           virCapsPtr caps,<br>
+                                           virDomainXMLOptionPtr xmlopt,<br>
+                                           unsigned int flags)<br>
+{<br>
+    size_t i, j;<br>
+    int n;<br>
+    virDomainDeviceDef device;<br>
+    xmlNodePtr *nodes = NULL;<br>
+    char *netprefix = NULL;<br>
+    int nhostdevs = 0;<br>
+<br>
+    device.type = VIR_DOMAIN_DEVICE_DISK;<br>
+<br>
+    if ((n = virXPathNodeSet("./disk", ctxt, &nodes)) < 0)<br>
+        goto error;<br>
+<br>
+    for (i = 0; i < n; i++) {<br>
+        virDomainDiskDefPtr disk = virDomainDiskDefParseXML(xmlopt,<br>
+                                                            nodes[i],<br>
+                                                            ctxt,<br>
+                                                            NULL,<br>
+                                                            def->seclabels,<br>
+                                                            def->nseclabels,<br>
+                                                            flags);<br>
+        if (!disk)<br>
+            goto error;<br>
+<br>
+        device.data.disk = disk;<br>
+        if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) < 0)<br>
+            goto error;<br>
+        VIR_FREE(disk);<br>
+    }<br>
+    VIR_FREE(nodes);<br>
+<br>
+    device.type = VIR_DOMAIN_DEVICE_CONTROLLER;<br>
+    /* analysis of the controller devices */<br>
+    if ((n = virXPathNodeSet("./controller", ctxt, &nodes)) < 0)<br>
+        goto error;<br>
+<br>
+    for (i = 0; i < n; i++) {<br>
+        virDomainControllerDefPtr controller = virDomainControllerDefParseXML(nodes[i],<br>
+                                                                              ctxt,<br>
+                                                                              flags);<br>
+        if (!controller)<br>
+            goto error;<br>
+<br>
+        device.data.controller = controller;<br>
+        if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) < 0)<br>
+            goto error;<br>
+        VIR_FREE(controller);<br>
+    }<br>
+    VIR_FREE(nodes);<br>
+<br>
+    device.type = VIR_DOMAIN_DEVICE_NET;<br>
+    if ((n = virXPathNodeSet("./interface", ctxt, &nodes)) < 0)<br>
+        goto error;<br>
+<br>
+    netprefix = caps->host.netprefix;<br>
+    for (i = 0; i < n; i++) {<br>
+        virDomainNetDefPtr net = virDomainNetDefParseXML(xmlopt,<br>
+                                                         nodes[i],<br>
+                                                         ctxt,<br>
+                                                         NULL,<br>
+                                                         netprefix,<br>
+                                                         flags);<br>
+        if (!net)<br>
+            goto error;<br>
+<br>
+        <a href="http://device.data.net" rel="noreferrer" target="_blank">device.data.net</a> = net;<br>
+        if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) < 0)<br>
+            goto error;<br>
+        VIR_FREE(net);<br>
+    }<br>
+    VIR_FREE(nodes);<br>
+<br>
+    /* analysis of the host devices */<br>
+    device.type = VIR_DOMAIN_DEVICE_HOSTDEV;<br>
+    if ((nhostdevs = virXPathNodeSet("./hostdev", ctxt, &nodes)) < 0)<br>
+        goto error;<br>
+    if (nhostdevs && devlist->count)<br>
+        goto misconfig;<br>
+    for (i = 0; i < nhostdevs; i++) {<br>
+        virDomainHostdevDefPtr hostdev;<br>
+<br>
+        hostdev = virDomainHostdevDefParseXML(xmlopt, nodes[i], ctxt,<br>
+                                              NULL, flags);<br>
+        if (!hostdev)<br>
+            goto error;<br>
+<br>
+        if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB ||<br>
+            hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {<br>
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",<br>
+                           _("Can't add host USB device: "<br>
+                             "USB is disabled in this host"));<br>
+            virDomainHostdevDefFree(hostdev);<br>
+            goto error;<br>
+        }<br>
+        device.data.hostdev = hostdev;<br>
+        for (j = 0; j < devlist->count; j++) {<br>
+            if (virDomainHostdevMatch(hostdev, devlist->devs[j]->data.hostdev)) {<br>
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",<br>
+                           _("Duplicate host devices in list"));<br>
+                goto error;<br>
+            }<br>
+        }<br>
+        if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) < 0)<br>
+            goto error;<br>
+        VIR_FREE(hostdev);<br>
+    }<br>
+    VIR_FREE(nodes);<br>
+<br>
+    /* Parse the RNG devices */<br>
+    device.type = VIR_DOMAIN_DEVICE_RNG;<br>
+    if ((n = virXPathNodeSet("./rng", ctxt, &nodes)) < 0)<br>
+        goto error;<br>
+    for (i = 0; i < n; i++) {<br>
+        virDomainRNGDefPtr rng = virDomainRNGDefParseXML(nodes[i],<br>
+                                                         ctxt,<br>
+                                                         flags);<br>
+        if (!rng)<br>
+            goto error;<br>
+<br>
+        device.data.rng = rng;<br>
+        if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) < 0)<br>
+            goto error;<br>
+        VIR_FREE(rng);<br>
+    }<br>
+    VIR_FREE(nodes);<br>
+<br>
+    device.type = VIR_DOMAIN_DEVICE_CHR;<br>
+    if ((n = virXPathNodeSet("./serial", ctxt, &nodes)) < 0)<br>
+        goto error;<br>
+<br>
+    for (i = 0; i < n; i++) {<br>
+        virDomainChrDefPtr chr = virDomainChrDefParseXML(ctxt,<br>
+                                                         nodes[i],<br>
+                                                         def->seclabels,<br>
+                                                         def->nseclabels,<br>
+                                                         flags);<br>
+        if (!chr)<br>
+            goto error;<br>
+<br>
+        if (chr->target.port == -1) {<br>
+            int maxport = -1;<br>
+            for (j = 0; j < i; j++) {<br>
+                if (def->serials[j]->target.port > maxport)<br>
+                    maxport = def->serials[j]->target.port;<br>
+            }<br>
+            chr->target.port = maxport + 1;<br>
+        }<br>
+        device.data.chr = chr;<br>
+        if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) < 0)<br>
+            goto error;<br>
+        VIR_FREE(chr);<br>
+    }<br>
+    VIR_FREE(nodes);<br>
+<br></blockquote><div><br></div><div>I realised the Character devices arent on PCI slot to get a PCI address and cant be hotplugged.</div><div>Will drop the character devices. </div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    if (nhostdevs  && nhostdevs != devlist->count)<br>
+        goto misconfig;<br>
+<br>
+    return 0;<br>
+ misconfig:<br>
+    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",<br>
+                   _("Shouldn't mix host devices with other devices"));<br>
+ error:<br>
+    return -1;<br>
+}<br>
+<br>
+<br>
+int<br>
+virDomainPCIMultifunctionDeviceDefParseNode(const char *xml,<br>
+                        const virDomainDef *def,<br>
+                        virDomainDeviceDefListPtr devlist,<br>
+                        virCapsPtr caps,<br>
+                        virDomainXMLOptionPtr xmlopt,<br>
+                        unsigned int flags)<br>
+{<br>
+    xmlXPathContextPtr ctxt = NULL;<br>
+    int ret = -1;<br>
+<br>
+    xmlDocPtr xmlptr;<br>
+<br>
+    if (!(xmlptr = virXMLParse(NULL, xml, _("(device_definition)")))) {<br>
+        /* We report error anyway later */<br>
+        return -1;<br>
+    }<br>
+<br>
+    ctxt = xmlXPathNewContext(xmlptr);<br>
+    if (ctxt == NULL) {<br>
+        virReportOOMError();<br>
+        goto cleanup;<br>
+    }<br>
+<br>
+    ctxt->node =  xmlDocGetRootElement(xmlptr);<br>
+    ret = virDomainPCIMultifunctionDeviceDefParseXML(ctxt, def, devlist,<br>
+                                                     caps, xmlopt, flags);<br>
+<br>
+ cleanup:<br>
+    xmlXPathFreeContext(ctxt);<br>
+    return ret;<br>
+}<br>
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h<br>
index b9e696d..9ddfbd1 100644<br>
--- a/src/conf/domain_conf.h<br>
+++ b/src/conf/domain_conf.h<br>
@@ -2462,6 +2462,20 @@ typedef enum {<br>
 typedef struct _virDomainXMLOption virDomainXMLOption;<br>
 typedef virDomainXMLOption *virDomainXMLOptionPtr;<br>
<br>
+struct virDomainDeviceDefList {<br>
+    virDomainDeviceDefPtr *devs;<br>
+    size_t count;<br>
+};<br>
+typedef struct virDomainDeviceDefList *virDomainDeviceDefListPtr;<br>
+<br>
+int<br>
+virDomainDeviceDefListAddCopy(virDomainDeviceDefListPtr list, virDomainDeviceDefPtr dev,<br>
+                              const virDomainDef *def,<br>
+                              virCapsPtr caps,<br>
+                              virDomainXMLOptionPtr xmlopt);<br>
+void virDomainDeviceDefListDispose(virDomainDeviceDefListPtr list);<br>
+<br>
+<br>
 /* Called once after everything else has been parsed, for adjusting<br>
  * overall domain defaults.  */<br>
 typedef int (*virDomainDefPostParseCallback)(virDomainDefPtr def,<br>
@@ -3176,6 +3190,14 @@ int virDomainDefGetVcpuPinInfoHelper(virDomainDefPtr def,<br>
<br>
 bool virDomainDefHasMemballoon(const virDomainDef *def) ATTRIBUTE_NONNULL(1);<br>
<br>
+int<br>
+virDomainPCIMultifunctionDeviceDefParseNode(const char *xml,<br>
+                        const virDomainDef *def,<br>
+                        virDomainDeviceDefListPtr devlist,<br>
+                        virCapsPtr caps,<br>
+                        virDomainXMLOptionPtr xmlopt,<br>
+                        unsigned int flags);<br>
+<br>
 char *virDomainObjGetShortName(virDomainObjPtr vm);<br>
<br>
 #endif /* __DOMAIN_CONF_H */<br>
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms<br>
index e4953b7..d6a60b5 100644<br>
--- a/src/libvirt_private.syms<br>
+++ b/src/libvirt_private.syms<br>
@@ -109,6 +109,7 @@ virDomainPCIAddressSetGrow;<br>
 virDomainPCIAddressSlotInUse;<br>
 virDomainPCIAddressValidate;<br>
 virDomainPCIControllerModelToConnectType;<br>
+virDomainPCIMultifunctionDeviceDefParseNode;<br>
 virDomainVirtioSerialAddrAssign;<br>
 virDomainVirtioSerialAddrAutoAssign;<br>
 virDomainVirtioSerialAddrIsComplete;<br>
@@ -249,6 +250,8 @@ virDomainDeviceAddressIsValid;<br>
 virDomainDeviceAddressTypeToString;<br>
 virDomainDeviceDefCopy;<br>
 virDomainDeviceDefFree;<br>
+virDomainDeviceDefListAddCopy;<br>
+virDomainDeviceDefListDispose;<br>
 virDomainDeviceDefParse;<br>
 virDomainDeviceFindControllerModel;<br>
 virDomainDeviceGetInfo;<br>
<br>
--<br>
libvir-list mailing list<br>
<a href="mailto:libvir-list@redhat.com">libvir-list@redhat.com</a><br>
<a href="https://www.redhat.com/mailman/listinfo/libvir-list" rel="noreferrer" target="_blank">https://www.redhat.com/mailman/listinfo/libvir-list</a><br>
</blockquote></div><br></div></div>