[libvirt] [PATCH v2 4/8] Introduce PCI Multifunction device parser
Shivaprasad bhat
shivaprasadbhat at gmail.com
Thu May 19 14:07:29 UTC 2016
On Thu, May 19, 2016 at 3:01 AM, Shivaprasad G Bhat <
shivaprasadbhat at gmail.com> 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 <sbhat at linux.vnet.ibm.com>
> ---
> 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
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20160519/f65f425c/attachment-0001.htm>
More information about the libvir-list
mailing list