This patch just introduces the parser function used by
the later patches. The parser disallows hostdevices to be
used with other virtio devices simultaneously.
Signed-off-by: Shivaprasad G Bhat <sbhat(a)linux.vnet.ibm.com>
---
src/conf/domain_conf.c | 227 ++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 22 ++++
src/libvirt_private.syms | 3 +
3 files changed, 252 insertions(+)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index ed0c471..6149d24 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -860,6 +860,36 @@ virDomainXMLOptionClassDispose(void *obj)
(xmlopt->config.privFree)(xmlopt->config.priv);
}
+/* virDomainDeviceDefListAddCopy - add a *copy* of the device to this list */
+int
+virDomainDeviceDefListAddCopy(virDomainDeviceDefListPtr list,
+ virDomainDeviceDefPtr dev,
+ const virDomainDef *def,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt)
+{
+ virDomainDeviceDefPtr copy = virDomainDeviceDefCopy(dev, def, caps, xmlopt);
+
+ if (!copy)
+ return -1;
+ if (VIR_APPEND_ELEMENT(list->devs, list->count, copy) < 0) {
+ virDomainDeviceDefFree(copy);
+ return -1;
+ }
+ return 0;
+}
+
+void virDomainDeviceDefListDispose(virDomainDeviceDefListPtr list)
+{
+ size_t i;
+
+ if (!list)
+ return;
+ for (i = 0; i < list->count; i++)
+ virDomainDeviceDefFree(list->devs[i]);
+ VIR_FREE(list);
+}
+
/**
* virDomainKeyWrapCipherDefParseXML:
*
@@ -24365,3 +24395,200 @@ virDomainObjGetShortName(virDomainObjPtr vm)
return ret;
}
+
+static int
+virDomainPCIMultifunctionDeviceDefParseXML(xmlXPathContextPtr ctxt,
+ const virDomainDef *def,
+ virDomainDeviceDefListPtr devlist,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ unsigned int flags)
+{
+ int ret = -1;
+ size_t i;
+ int n;
+ virDomainDeviceDef device;
+ xmlNodePtr *nodes = NULL;
+ char *netprefix = NULL;
+ int nhostdevs = 0;
+
+ device.type = VIR_DOMAIN_DEVICE_DISK;
+
+ if ((n = virXPathNodeSet("./disk", ctxt, &nodes)) < 0)
+ goto error;
+
+ for (i = 0; i < n; i++) {
+ virDomainDiskDefPtr disk = virDomainDiskDefParseXML(xmlopt,
+ nodes[i],
+ ctxt,
+ NULL,
+ def->seclabels,
+ def->nseclabels,
+ flags);
+ if (!disk)
+ goto error;
+
+ device.data.disk = disk;
+ if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) <
0)
+ goto error;
+ VIR_FREE(disk);
+ }
+ VIR_FREE(nodes);
+
+ device.type = VIR_DOMAIN_DEVICE_CONTROLLER;
+ /* analysis of the controller devices */
+ if ((n = virXPathNodeSet("./controller", ctxt, &nodes)) < 0)
+ goto error;
+
+ for (i = 0; i < n; i++) {
+ virDomainControllerDefPtr controller = virDomainControllerDefParseXML(nodes[i],
+ ctxt,
+ flags);
+ if (!controller)
+ goto error;
+
+ device.data.controller = controller;
+ if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) <
0)
+ goto error;
+ VIR_FREE(controller);
+ }
+ VIR_FREE(nodes);
+
+ device.type = VIR_DOMAIN_DEVICE_NET;
+ if ((n = virXPathNodeSet("./interface", ctxt, &nodes)) < 0)
+ goto error;
+
+ netprefix = caps->host.netprefix;
+ for (i = 0; i < n; i++) {
+ virDomainNetDefPtr net = virDomainNetDefParseXML(xmlopt,
+ nodes[i],
+ ctxt,
+ NULL,
+ netprefix,
+ flags);
+ if (!net)
+ goto error;
+
+
device.data.net = net;
+ if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) <
0)
+ goto error;
+ VIR_FREE(net);
+ }
+ VIR_FREE(nodes);
+
+ /* analysis of the host devices */
+ device.type = VIR_DOMAIN_DEVICE_HOSTDEV;
+ if ((nhostdevs = virXPathNodeSet("./hostdev", ctxt, &nodes)) < 0)
+ goto error;
+ for (i = 0; i < nhostdevs; i++) {
+ virDomainHostdevDefPtr hostdev;
+
+ hostdev = virDomainHostdevDefParseXML(xmlopt, nodes[i], ctxt,
+ NULL, flags);
+ if (!hostdev)
+ goto error;
+
+ if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB ||
+ hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Can't add host USB device: "
+ "USB is disabled in this host"));
+ virDomainHostdevDefFree(hostdev);
+ goto error;
+ }
+ device.data.hostdev = hostdev;
+ if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) <
0)
+ goto error;
+ VIR_FREE(hostdev);
+ }
+ VIR_FREE(nodes);
+
+ /* Parse the RNG devices */
+ device.type = VIR_DOMAIN_DEVICE_RNG;
+ if ((n = virXPathNodeSet("./rng", ctxt, &nodes)) < 0)
+ goto error;
+ for (i = 0; i < n; i++) {
+ virDomainRNGDefPtr rng = virDomainRNGDefParseXML(nodes[i],
+ ctxt,
+ flags);
+ if (!rng)
+ goto error;
+
+ device.data.rng = rng;
+ if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) <
0)
+ goto error;
+ VIR_FREE(rng);
+ }
+ VIR_FREE(nodes);
+
+ device.type = VIR_DOMAIN_DEVICE_CHR;
+ if ((n = virXPathNodeSet("./serial", ctxt, &nodes)) < 0)
+ goto error;
+
+ for (i = 0; i < n; i++) {
+ virDomainChrDefPtr chr = virDomainChrDefParseXML(ctxt,
+ nodes[i],
+ def->seclabels,
+ def->nseclabels,
+ flags);
+ if (!chr)
+ goto error;
+
+ if (chr->target.port == -1) {
+ int maxport = -1;
+ size_t j;
+ for (j = 0; j < i; j++) {
+ if (def->serials[j]->target.port > maxport)
+ maxport = def->serials[j]->target.port;
+ }
+ chr->target.port = maxport + 1;
+ }
+ device.data.chr = chr;
+ if (virDomainDeviceDefListAddCopy(devlist, &device, def, caps, xmlopt) <
0)
+ goto error;
+ VIR_FREE(chr);
+ }
+ VIR_FREE(nodes);
+
+ if (nhostdevs)
+ ret = nhostdevs != devlist->count ? -1 : 0;
+ else
+ ret = 0;
+
+ error:
+ return ret;
+}
+
+
+int
+virDomainPCIMultifunctionDeviceDefParseNode(const char *xml,
+ const virDomainDef *def,
+ virDomainDeviceDefListPtr devlist,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ unsigned int flags)
+{
+ xmlXPathContextPtr ctxt = NULL;
+ int ret = -1;
+
+ xmlDocPtr xmlptr;
+
+ if (!(xmlptr = virXMLParse(NULL, xml, _("(device_definition)")))) {
+ /* We report error anyway later */
+ return -1;
+ }
+
+ ctxt = xmlXPathNewContext(xmlptr);
+ if (ctxt == NULL) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ ctxt->node = xmlDocGetRootElement(xmlptr);
+ ret = virDomainPCIMultifunctionDeviceDefParseXML(ctxt, def, devlist,
+ caps, xmlopt, flags);
+
+ cleanup:
+ xmlXPathFreeContext(ctxt);
+ return ret;
+}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index b9e696d..9ddfbd1 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2462,6 +2462,20 @@ typedef enum {
typedef struct _virDomainXMLOption virDomainXMLOption;
typedef virDomainXMLOption *virDomainXMLOptionPtr;
+struct virDomainDeviceDefList {
+ virDomainDeviceDefPtr *devs;
+ size_t count;
+};
+typedef struct virDomainDeviceDefList *virDomainDeviceDefListPtr;
+
+int
+virDomainDeviceDefListAddCopy(virDomainDeviceDefListPtr list, virDomainDeviceDefPtr dev,
+ const virDomainDef *def,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt);
+void virDomainDeviceDefListDispose(virDomainDeviceDefListPtr list);
+
+
/* Called once after everything else has been parsed, for adjusting
* overall domain defaults. */
typedef int (*virDomainDefPostParseCallback)(virDomainDefPtr def,
@@ -3176,6 +3190,14 @@ int virDomainDefGetVcpuPinInfoHelper(virDomainDefPtr def,
bool virDomainDefHasMemballoon(const virDomainDef *def) ATTRIBUTE_NONNULL(1);
+int
+virDomainPCIMultifunctionDeviceDefParseNode(const char *xml,
+ const virDomainDef *def,
+ virDomainDeviceDefListPtr devlist,
+ virCapsPtr caps,
+ virDomainXMLOptionPtr xmlopt,
+ unsigned int flags);
+
char *virDomainObjGetShortName(virDomainObjPtr vm);
#endif /* __DOMAIN_CONF_H */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e4953b7..d6a60b5 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -109,6 +109,7 @@ virDomainPCIAddressSetGrow;
virDomainPCIAddressSlotInUse;
virDomainPCIAddressValidate;
virDomainPCIControllerModelToConnectType;
+virDomainPCIMultifunctionDeviceDefParseNode;
virDomainVirtioSerialAddrAssign;
virDomainVirtioSerialAddrAutoAssign;
virDomainVirtioSerialAddrIsComplete;
@@ -249,6 +250,8 @@ virDomainDeviceAddressIsValid;
virDomainDeviceAddressTypeToString;
virDomainDeviceDefCopy;
virDomainDeviceDefFree;
+virDomainDeviceDefListAddCopy;
+virDomainDeviceDefListDispose;
virDomainDeviceDefParse;
virDomainDeviceFindControllerModel;
virDomainDeviceGetInfo;