From: Shivaprasad G Bhat <sbhat(a)linux.vnet.ibm.com>
Signed-off-by: Shivaprasad G Bhat <sbhat(a)linux.vnet.ibm.com>
Signed-off-by: Daniel Henrique Barboza <danielhb413(a)gmail.com>
---
src/qemu/qemu_domain.c | 74 ++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_domain.h | 7 ++++
2 files changed, 81 insertions(+)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index d5e3d1a3cc..0471a37803 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -13391,6 +13391,80 @@ qemuProcessEventFree(struct qemuProcessEvent *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;
+
+ for (i = 0; i < devlist->count; i++) {
+ virDomainDeviceInfoPtr info = virDomainDeviceGetInfo(devlist->devs[i]);
+
+ if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+ info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
+ return -1;
+ }
+
+ if (devlist->devs[i]->type == VIR_DOMAIN_DEVICE_HOSTDEV) {
+ virDomainHostdevDefPtr hostdev = devlist->devs[i]->data.hostdev;
+
+ if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+virDomainDeviceDefListPtr
+qemuDomainDeviceParseXMLMany(const char *xml,
+ virDomainDeviceDefListDataPtr data,
+ void *parseOpaque,
+ unsigned int parse_flags)
+{
+ virDomainDeviceDefListPtr devlist = NULL;
+
+ if (isPCIMultifunctionDeviceXML(xml)) {
+ if (!(devlist = virDomainDeviceDefParseXMLMany(xml, data->def,
+ data->xmlopt,
+ parseOpaque,
+ parse_flags)))
+ return NULL;
+
+ if (qemuDomainValidateMultifunctionDeviceList(devlist) < 0)
+ goto cleanup;
+ } else {
+ virDomainDeviceDefPtr dev = virDomainDeviceDefParse(xml, data->def,
+ data->xmlopt,
+ parseOpaque,
+ parse_flags);
+ if (!dev || VIR_ALLOC(devlist) < 0)
+ return NULL;
+
+ if (VIR_APPEND_ELEMENT(devlist->devs, devlist->count, dev) < 0)
+ goto cleanup;
+ }
+
+ return devlist;
+
+ cleanup:
+ virDomainDeviceDefListFree(devlist);
+ return NULL;
+}
+
+
char *
qemuDomainGetManagedPRSocketPath(qemuDomainObjPrivatePtr priv)
{
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index b601d52126..31c843de96 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -1291,6 +1291,13 @@ qemuDomainNVRAMPathGenerate(virQEMUDriverConfigPtr cfg,
virDomainEventSuspendedDetailType
qemuDomainPausedReasonToSuspendedEvent(virDomainPausedReason reason);
+
+virDomainDeviceDefListPtr
+qemuDomainDeviceParseXMLMany(const char *xml,
+ virDomainDeviceDefListDataPtr data,
+ void *parseOpaque,
+ unsigned int parse_flags);
+
int
qemuDomainValidateActualNetDef(const virDomainNetDef *net,
virQEMUCapsPtr qemuCaps);
--
2.26.2