Signed-off-by: Shivaprasad G Bhat <sbhat(a)linux.vnet.ibm.com>
---
src/qemu/qemu_domain.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_domain.h | 5 ++++
2 files changed, 72 insertions(+)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 12ed68a89b..c0a0af525f 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -11842,3 +11842,70 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
}
VIR_FREE(event);
}
+
+
+static bool isPCIMultifunctionDeviceXML(const char *xml)
+{
+ xmlDocPtr xmlptr;
+
+ if (!(xmlptr = virXMLParse(NULL, xml, _("(device_definition)")))) {
+ /* We report error anyway later */
+ return false;
+ }
+
+ return STREQ((const char *)(xmlDocGetRootElement(xmlptr))->name,
"devices");
+}
+
+static
+int qemuDomainValidateMultifunctionDeviceList(virDomainDeviceDefListPtr devlist)
+{
+ size_t i;
+ virDomainHostdevDefPtr hostdev = NULL;
+ virDomainDeviceInfoPtr info;
+
+ for (i = 0; i < devlist->count; i++) {
+ info = virDomainDeviceGetInfo(devlist->devs[i]);
+ if (devlist->devs[i]->type == VIR_DOMAIN_DEVICE_HOSTDEV)
+ hostdev = devlist->devs[i]->data.hostdev;
+
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ return -1;
+
+ if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+ info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+virDomainDeviceDefListPtr
+qemuDomainDeviceParseXMLMany(const char *xml,
+ virDomainDeviceDefListDataPtr data,
+ unsigned int parse_flags)
+{
+ virDomainDeviceDefListPtr devlist = NULL;
+
+ if (isPCIMultifunctionDeviceXML(xml)) {
+ if (!(devlist = virDomainDeviceDefParseXMLMany(xml, data->def,
+ data->caps, data->xmlopt,
+ parse_flags)))
+ goto cleanup;
+
+ if (qemuDomainValidateMultifunctionDeviceList(devlist) < 0)
+ goto cleanup;
+ } else {
+ virDomainDeviceDefPtr dev = virDomainDeviceDefParse(xml, data->def,
+ data->caps,
data->xmlopt,
+ parse_flags);
+ if (!dev || VIR_ALLOC(devlist) < 0)
+ goto cleanup;
+
+ if (VIR_APPEND_ELEMENT(devlist->devs, devlist->count, dev) < 0)
+ goto cleanup;
+ }
+
+ cleanup:
+ return devlist;
+}
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index fbfc994652..339d0ba82c 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -1011,4 +1011,9 @@ qemuDomainPrepareDiskSource(virDomainDiskDefPtr disk,
qemuDomainObjPrivatePtr priv,
virQEMUDriverConfigPtr cfg);
+virDomainDeviceDefListPtr
+qemuDomainDeviceParseXMLMany(const char *xml,
+ virDomainDeviceDefListDataPtr data,
+ unsigned int parse_flags);
+
#endif /* __QEMU_DOMAIN_H__ */