[libvirt] [PATCH 7/9 v2] nodedev: Fix the improper logic when enumerating SRIOV VF
Osier Yang
jyang at redhat.com
Tue Jan 15 09:59:47 UTC 2013
On 2013年01月15日 17:56, Osier Yang wrote:
> pciGetVirtualFunctions returns 0 even if there is no "virtfn"
> entry under the device sysfs path.
>
> And pciGetVirtualFunctions returns -1 when it fails to get
> the PCI config space of one VF, however, with keeping the
> the VFs already detected.
>
> That's why udevProcessPCI and gather_pci_cap use logic like:
>
> if (!pciGetVirtualFunctions(syspath,
> &data->pci_dev.virtual_functions,
> &data->pci_dev.num_virtual_functions) ||
> data->pci_dev.num_virtual_functions> 0)
> data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION;
>
> to tag the PCI device with "virtual_function" cap.
>
> However, this results in a VF will aslo get "virtual_function" cap.
>
> This patch fixes it by:
> * Ignoring the VF which has failure of getting PCI config space
> (given that the successfully detected VFs are kept , it makes
> sense to not give up on the failure of one VF too) with a warning,
> so pciGetVirtualFunctions will not return -1 except out of memory.
>
> * Free the allocated *virtual_functions when out of memory
>
> And thus the logic can be changed to:
>
> /* Out of memory */
> int ret = pciGetVirtualFunctions(syspath,
> &data->pci_dev.virtual_functions,
> &data->pci_dev.num_virtual_functions);
>
> if (ret< 0 )
> goto out;
> if (data->pci_dev.num_virtual_functions> 0)
> data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION;
> ---
> src/node_device/node_device_hal.c | 12 +++++++--
> src/node_device/node_device_udev.c | 11 ++++++--
> src/util/virpci.c | 46 +++++++++++++++++++++---------------
> 3 files changed, 44 insertions(+), 25 deletions(-)
>
> diff --git a/src/node_device/node_device_hal.c b/src/node_device/node_device_hal.c
> index e64d6ac..6da5873 100644
> --- a/src/node_device/node_device_hal.c
> +++ b/src/node_device/node_device_hal.c
> @@ -151,9 +151,15 @@ static int gather_pci_cap(LibHalContext *ctx, const char *udi,
> if (!pciGetPhysicalFunction(sysfs_path,&d->pci_dev.physical_function))
> d->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION;
>
> - if (!pciGetVirtualFunctions(sysfs_path,&d->pci_dev.virtual_functions,
> -&d->pci_dev.num_virtual_functions) ||
> - d->pci_dev.num_virtual_functions> 0)
> + int ret = pciGetVirtualFunctions(sysfs_path,
> +&d->pci_dev.virtual_functions,
> +&d->pci_dev.num_virtual_functions);
> + if (ret< 0) {
> + VIR_FREE(sysfs_path);
> + return -1;
> + }
> +
> + if (d->pci_dev.num_virtual_functions> 0)
> d->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION;
>
> VIR_FREE(sysfs_path);
> diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
> index 62f6320..a90217d 100644
> --- a/src/node_device/node_device_udev.c
> +++ b/src/node_device/node_device_udev.c
> @@ -416,6 +416,7 @@ static int udevProcessPCI(struct udev_device *device,
> union _virNodeDevCapData *data =&def->caps->data;
> int ret = -1;
> char *p;
> + int rc;
>
> syspath = udev_device_get_syspath(device);
>
> @@ -484,9 +485,13 @@ static int udevProcessPCI(struct udev_device *device,
> if (!pciGetPhysicalFunction(syspath,&data->pci_dev.physical_function))
> data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION;
>
> - if (!pciGetVirtualFunctions(syspath,&data->pci_dev.virtual_functions,
> -&data->pci_dev.num_virtual_functions) ||
> - data->pci_dev.num_virtual_functions> 0)
> + rc = pciGetVirtualFunctions(syspath,
> +&data->pci_dev.virtual_functions,
> +&data->pci_dev.num_virtual_functions);
> + /* Out of memory */
> + if (rc< 0)
> + goto out;
> + else if (!rc&& (data->pci_dev.num_virtual_functions> 0))
> data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION;
>
> ret = 0;
> diff --git a/src/util/virpci.c b/src/util/virpci.c
> index 0fb9923..ee4b3a8 100644
> --- a/src/util/virpci.c
> +++ b/src/util/virpci.c
> @@ -1968,6 +1968,7 @@ pciGetVirtualFunctions(const char *sysfs_path,
> unsigned int *num_virtual_functions)
> {
> int ret = -1;
> + int i;
> DIR *dir = NULL;
> struct dirent *entry = NULL;
> char *device_link = NULL;
> @@ -1989,45 +1990,52 @@ pciGetVirtualFunctions(const char *sysfs_path,
> *num_virtual_functions = 0;
> while ((entry = readdir(dir))) {
> if (STRPREFIX(entry->d_name, "virtfn")) {
> + struct pci_config_address *config_addr = NULL;
>
> if (virBuildPath(&device_link, sysfs_path, entry->d_name) == -1) {
> virReportOOMError();
> - goto out;
> + goto error;
> }
>
> VIR_DEBUG("Number of virtual functions: %d",
> *num_virtual_functions);
> - if (VIR_REALLOC_N(*virtual_functions,
> - (*num_virtual_functions) + 1) != 0) {
> - virReportOOMError();
> - VIR_FREE(device_link);
> - goto out;
> - }
>
> if (pciGetPciConfigAddressFromSysfsDeviceLink(device_link,
> -&((*virtual_functions)[*num_virtual_functions])) !=
> +&config_addr) !=
> SRIOV_FOUND) {
> - /* We should not get back SRIOV_NOT_FOUND in this
> - * case, so if we do, it's an error. */
> - virReportError(VIR_ERR_INTERNAL_ERROR,
> - _("Failed to get SR IOV function from device "
> - "link '%s'"), device_link);
> + VIR_WARN("Failed to get SRIOV function from device "
> + "link '%s'", device_link);
> VIR_FREE(device_link);
> - goto out;
> - } else {
> - (*num_virtual_functions)++;
> + continue;
> }
> +
> + if (VIR_ALLOC_N(*virtual_functions,
> + *num_virtual_functions + 1)< 0) {
> + virReportOOMError();
> + VIR_FREE(config_addr);
> + goto error;
> + }
> +
> + (*virtual_functions)[*num_virtual_functions] = config_addr;
> + (*num_virtual_functions)++;
> VIR_FREE(device_link);
> }
> }
>
> ret = 0;
> -
> -out:
> +cleanup:
> + VIR_FREE(device_link);
> if (dir)
> closedir(dir);
> -
> return ret;
> +
> +error:
> + if (*virtual_functions) {
> + for (i = 0; i< *num_virtual_functions; i++)
> + VIR_FREE((*virtual_functions)[i]);
> + VIR_FREE(*virtual_functions);
> + }
> + goto cleanup;
> }
>
> /*
Eh, changes on *_udev.c was lost when committing. With the following
diff squashed in:
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: diff2
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20130115/508b7ee5/attachment-0001.ksh>
More information about the libvir-list
mailing list