On Thu, May 19, 2016 at 3:01 AM, Shivaprasad G Bhat < [email protected]> wrote:
> 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 <[email protected]> > --- > src/conf/domain_conf.c | 236 > ++++++++++++++++++++++++++++++++++++++++++++++ > src/conf/domain_conf.h | 22 ++++ > src/libvirt_private.syms | 3 + > 3 files changed, 261 insertions(+) > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index ed0c471..e946147 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,209 @@ virDomainObjGetShortName(virDomainObjPtr vm) > > return ret; > } > + > +static int > +virDomainPCIMultifunctionDeviceDefParseXML(xmlXPathContextPtr ctxt, > + const virDomainDef *def, > + virDomainDeviceDefListPtr > devlist, > + virCapsPtr caps, > + virDomainXMLOptionPtr xmlopt, > + unsigned int flags) > +{ > + size_t i, j; > + 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; > + if (nhostdevs && devlist->count) > + goto misconfig; > + 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; > + for (j = 0; j < devlist->count; j++) { > + if (virDomainHostdevMatch(hostdev, > devlist->devs[j]->data.hostdev)) { > + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("Duplicate host devices in list")); > + goto error; > + } > + } > + 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; > + 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); > + > I realised the Character devices arent on PCI slot to get a PCI address and cant be hotplugged. Will drop the character devices. > + if (nhostdevs && nhostdevs != devlist->count) > + goto misconfig; > + > + return 0; > + misconfig: > + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", > + _("Shouldn't mix host devices with other devices")); > + error: > + return -1; > +} > + > + > +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; > > -- > libvir-list mailing list > [email protected] > https://www.redhat.com/mailman/listinfo/libvir-list >
-- libvir-list mailing list [email protected] https://www.redhat.com/mailman/listinfo/libvir-list
