conf: allow type='pci' addresses with no address attributes specified

Prior to this, <address type='pci'/> wasn't allowed when parsing
(domain+bus+slot+function needed to be a "valid" PCI address, meaning
that at least one of domain/bus/slot had to be non-0), the RNG
required bus to be specified, and if type was set to PCI when
formatting, domain+bus+slot+function would always be output.

This makes all the address attributes optional during parse and RNG
validation, and suppresses domain+bus+slot+function if domain+bus+slot
are all 0 (NB: if d+b+s are all 0, any value for function is
nonsensical as that will never happen in the real world, and after
the next patch we will always assign a real working address to any
empty PCI address before it is ever output to anywhere).

Note that explicitly setting all attributes to 0 is equivalent to
setting none of them, which is okay, since 0000:00:00 is reserved in
any PCI bus setup, and can't be used anyway.
This commit is contained in:
Laine Stump 2016-05-17 14:03:00 -04:00
parent 9a81a36353
commit 8f578716c7
4 changed files with 23 additions and 12 deletions

View File

@ -2930,7 +2930,13 @@
(<span class="since">since 0.9.7, requires QEMU (<span class="since">since 0.9.7, requires QEMU
0.13</span>). <code>multifunction</code> defaults to 'off', 0.13</span>). <code>multifunction</code> defaults to 'off',
but should be set to 'on' for function 0 of a slot that will but should be set to 'on' for function 0 of a slot that will
have multiple functions used. have multiple functions used.<br/>
<span class="since">Since 1.3.5</span>, some hypervisor
drivers may accept an <code>&lt;address type='pci'/&gt;</code>
element with no other attributes as an explicit request to
assign a PCI address for the device rather than some other
type of address that may also be appropriate for that same
device (e.g. virtio-mmio).
</dd> </dd>
<dt><code>drive</code></dt> <dt><code>drive</code></dt>
<dd>Drive addresses have the following additional <dd>Drive addresses have the following additional

View File

@ -83,9 +83,11 @@
<ref name="pciDomain"/> <ref name="pciDomain"/>
</attribute> </attribute>
</optional> </optional>
<attribute name="bus"> <optional>
<ref name="pciBus"/> <attribute name="bus">
</attribute> <ref name="pciBus"/>
</attribute>
</optional>
<optional> <optional>
<attribute name="slot"> <attribute name="slot">
<ref name="pciSlot"/> <ref name="pciSlot"/>

View File

@ -1,7 +1,7 @@
/* /*
* device_conf.c: device XML handling * device_conf.c: device XML handling
* *
* Copyright (C) 2006-2015 Red Hat, Inc. * Copyright (C) 2006-2016 Red Hat, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -90,7 +90,7 @@ int virPCIDeviceAddressIsValid(virPCIDeviceAddressPtr addr,
addr->function); addr->function);
return 0; return 0;
} }
if (!(addr->domain || addr->bus || addr->slot)) { if (virPCIDeviceAddressIsEmpty(addr)) {
if (report) if (report)
virReportError(VIR_ERR_XML_ERROR, "%s", virReportError(VIR_ERR_XML_ERROR, "%s",
_("Invalid PCI address 0000:00:00, at least " _("Invalid PCI address 0000:00:00, at least "
@ -152,7 +152,7 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
goto cleanup; goto cleanup;
} }
if (!virPCIDeviceAddressIsValid(addr, true)) if (!virPCIDeviceAddressIsEmpty(addr) && !virPCIDeviceAddressIsValid(addr, true))
goto cleanup; goto cleanup;
ret = 0; ret = 0;

View File

@ -4522,11 +4522,14 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
switch ((virDomainDeviceAddressType) info->type) { switch ((virDomainDeviceAddressType) info->type) {
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI: case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
virBufferAsprintf(buf, " domain='0x%.4x' bus='0x%.2x' slot='0x%.2x' function='0x%.1x'", if (!virPCIDeviceAddressIsEmpty(&info->addr.pci)) {
info->addr.pci.domain, virBufferAsprintf(buf, " domain='0x%.4x' bus='0x%.2x' "
info->addr.pci.bus, "slot='0x%.2x' function='0x%.1x'",
info->addr.pci.slot, info->addr.pci.domain,
info->addr.pci.function); info->addr.pci.bus,
info->addr.pci.slot,
info->addr.pci.function);
}
if (info->addr.pci.multi) { if (info->addr.pci.multi) {
virBufferAsprintf(buf, " multifunction='%s'", virBufferAsprintf(buf, " multifunction='%s'",
virTristateSwitchTypeToString(info->addr.pci.multi)); virTristateSwitchTypeToString(info->addr.pci.multi));