[libvirt] [PATCH 2/7] qemu: move PCI address check out of qemuPCIAddressAsString
Laine Stump
laine at laine.org
Thu Apr 4 17:55:47 UTC 2013
On 04/03/2013 11:50 AM, Ján Tomko wrote:
> Move bus and domain checks from qemuPCIAddressAsString to
> a separate function and add a check for function and slot
> so that we can switch from a hash table to an array.
>
> Remove redundant checks in qemuBuildDeviceAddressStr.
> ---
> src/qemu/qemu_command.c | 111 +++++++++++++++++++++++++++++-------------------
> 1 file changed, 68 insertions(+), 43 deletions(-)
>
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 8321dcd..a16d5f1 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -1193,17 +1193,43 @@ struct _qemuDomainPCIAddressSet {
> };
>
>
> +/* Check the PCI address
> + * Returns -1 if the address is unusable
> + * 0 if it's OK.
> + */
> +static int qemuPCIAddressCheck(qemuDomainPCIAddressSetPtr addrs ATTRIBUTE_UNUSED,
> + virDevicePCIAddressPtr addr)
How about naming this qemuPCIAddressValidate()? (This is especially good
since the verb "Check" is used elsewhere in this file to mean "check to
see if this is *in use*")
> +{
> + if (addr->domain != 0) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("Only PCI domain 0 is available"));
> + return -1;
> + }
> + if (addr->bus != 0) {
> + virReportError(VIR_ERR_XML_ERROR, "%s",
> + _("Only PCI bus 0 is available"));
> + return -1;
> + }
> + if (addr->function >= QEMU_PCI_ADDRESS_LAST_FUNCTION) {
> + virReportError(VIR_ERR_XML_ERROR,
> + _("Invalid PCI address: function must be < %u"),
> + QEMU_PCI_ADDRESS_LAST_FUNCTION);
> + return -1;
> + }
> + if (addr->slot >= QEMU_PCI_ADDRESS_LAST_SLOT) {
> + virReportError(VIR_ERR_XML_ERROR,
> + _("Invalid PCI address: slot must be < %u"),
> + QEMU_PCI_ADDRESS_LAST_SLOT);
> + return -1;
> + }
> + return 0;
> +}
> +
> +
> static char *qemuPCIAddressAsString(virDevicePCIAddressPtr addr)
> {
> char *str;
>
> - if (addr->domain != 0 ||
> - addr->bus != 0) {
> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> - _("Only PCI domain 0 and bus 0 are available"));
> - return NULL;
> - }
> -
Yes, definitely by the time we are converting this to a string it should
have already been validated.
> if (virAsprintf(&str, "%d:%d:%d.%d",
> addr->domain,
> addr->bus,
> @@ -1222,7 +1248,8 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
> void *opaque)
> {
> int ret = -1;
> - char *addr = NULL;
> + char *str = NULL;
> + virDevicePCIAddressPtr addr = &info->addr.pci;
> qemuDomainPCIAddressSetPtr addrs = opaque;
>
> if ((info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
> @@ -1235,57 +1262,60 @@ static int qemuCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
> return 0;
> }
>
> - addr = qemuPCIAddressAsString(&info->addr.pci);
> - if (!addr)
> + if (qemuPCIAddressCheck(addrs, addr) < 0)
> + return -1;
> +
> + str = qemuPCIAddressAsString(addr);
> + if (!str)
> goto cleanup;
I prefer putting the assignment into the if condition:
if (!(str = qemuPCIAddressAsString(addr)))
goto cleanup;
>
> - if (virHashLookup(addrs->used, addr)) {
> + if (virHashLookup(addrs->used, str)) {
> if (info->addr.pci.function != 0) {
> virReportError(VIR_ERR_XML_ERROR,
> _("Attempted double use of PCI Address '%s' "
> "(may need \"multifunction='on'\" for device on function 0)"),
> - addr);
> + str);
> } else {
> virReportError(VIR_ERR_XML_ERROR,
> - _("Attempted double use of PCI Address '%s'"), addr);
> + _("Attempted double use of PCI Address '%s'"), str);
> }
> goto cleanup;
> }
>
> - VIR_DEBUG("Remembering PCI addr %s", addr);
> - if (virHashAddEntry(addrs->used, addr, addr) < 0)
> + VIR_DEBUG("Remembering PCI addr %s", str);
> + if (virHashAddEntry(addrs->used, str, str) < 0)
> goto cleanup;
> - addr = NULL;
> + str = NULL;
>
> if ((info->addr.pci.function == 0) &&
> (info->addr.pci.multi != VIR_DEVICE_ADDRESS_PCI_MULTI_ON)) {
> /* a function 0 w/o multifunction=on must reserve the entire slot */
> - virDevicePCIAddress tmp_addr = info->addr.pci;
> + virDevicePCIAddress tmp_addr = *addr;
> unsigned int *func = &tmp_addr.function;
>
> for (*func = 1; *func < QEMU_PCI_ADDRESS_LAST_FUNCTION; (*func)++) {
> - addr = qemuPCIAddressAsString(&tmp_addr);
> - if (!addr)
> + str = qemuPCIAddressAsString(&tmp_addr);
> + if (!str)
> goto cleanup;
Again, as long as you're modifying the lines, might as well stuff the
assignment into the if condition.
>
> - if (virHashLookup(addrs->used, addr)) {
> + if (virHashLookup(addrs->used, str)) {
> virReportError(VIR_ERR_XML_ERROR,
> _("Attempted double use of PCI Address '%s' "
> "(need \"multifunction='off'\" for device "
> "on function 0)"),
> - addr);
> + str);
> goto cleanup;
> }
>
> - VIR_DEBUG("Remembering PCI addr %s (multifunction=off for function 0)", addr);
> - if (virHashAddEntry(addrs->used, addr, addr))
> + VIR_DEBUG("Remembering PCI addr %s (multifunction=off for function 0)", str);
> + if (virHashAddEntry(addrs->used, str, str))
> goto cleanup;
> - addr = NULL;
> + str = NULL;
> }
> }
> ret = 0;
> cleanup:
> - VIR_FREE(addr);
> + VIR_FREE(str);
> return ret;
> }
>
> @@ -1385,6 +1415,9 @@ static int qemuDomainPCIAddressCheckSlot(qemuDomainPCIAddressSetPtr addrs,
I just noticed that the (existing) comment for this function isn't
worded very well. As long as you're modifying things, could you fix that
too? (just s/the other/another/g)
Hmm, and now that I've suggested changing the name of
qemuPCIAddressCheck because of this function using the word "Check"
differently, I'm thinking *this* function could be better named as well.
How about qemuDomainPCIAddressInUse()? Also, I think it should return
true or false, not 0 or -1 (with associated adjustments in callers).
> virDevicePCIAddress tmp_addr = *addr;
> unsigned int *func = &(tmp_addr.function);
>
> + if (qemuPCIAddressCheck(addrs, addr) < 0)
> + return -1;
> +
And as a matter of fact, I think you shouldn't be validating the PCI
address here - in two of the 3 callers, a fixed hard-coded pci address
is constructed (so you know that it's always valid), and in the 3rd
caller, it's being done inside a loop whose index self-limits the PCI
address to a valid range. (This is good, because if you left the call to
the validation in here, you would have to have a tri-state return value
to allow for failure as well as inuse/free).
> for (*func = 0; *func < QEMU_PCI_ADDRESS_LAST_FUNCTION; (*func)++) {
> str = qemuPCIAddressAsString(&tmp_addr);
> if (!str)
> @@ -1406,6 +1439,9 @@ int qemuDomainPCIAddressReserveAddr(qemuDomainPCIAddressSetPtr addrs,
> {
> char *str;
>
> + if (qemuPCIAddressCheck(addrs, addr) < 0)
> + return -1;
> +
> str = qemuPCIAddressAsString(addr);
> if (!str)
> return -1;
> @@ -1479,6 +1515,9 @@ int qemuDomainPCIAddressReleaseAddr(qemuDomainPCIAddressSetPtr addrs,
> char *str;
> int ret;
>
> + if (qemuPCIAddressCheck(addrs, addr) < 0)
> + return -1;
> +
> str = qemuPCIAddressAsString(addr);
> if (!str)
> return -1;
> @@ -1498,6 +1537,9 @@ int qemuDomainPCIAddressReleaseSlot(qemuDomainPCIAddressSetPtr addrs,
> virDevicePCIAddress tmp_addr = *addr;
> unsigned int *func = &tmp_addr.function;
>
> + if (qemuPCIAddressCheck(addrs, addr) < 0)
> + return -1;
> +
> for (*func = 0; *func < QEMU_PCI_ADDRESS_LAST_FUNCTION; (*func)++) {
> str = qemuPCIAddressAsString(&tmp_addr);
> if (!str)
> @@ -1965,24 +2007,7 @@ qemuBuildDeviceAddressStr(virBufferPtr buf,
> virQEMUCapsPtr qemuCaps)
> {
> if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
> - if (info->addr.pci.domain != 0) {
> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> - _("Only PCI device addresses with domain=0 are supported"));
> - return -1;
> - }
> - if (info->addr.pci.bus != 0) {
> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> - _("Only PCI device addresses with bus=0 are supported"));
> - return -1;
> - }
> - if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
> - if (info->addr.pci.function > 7) {
> - virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> - _("The function of PCI device addresses must "
> - "be less than 8"));
> - return -1;
> - }
> - } else {
> + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION)) {
> if (info->addr.pci.function != 0) {
> virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> _("Only PCI device addresses with function=0 "
Looks fine aside from the nits I listed above.
More information about the libvir-list
mailing list