In current implemention, mdev_types caps keep constant all the time. But, it is possible that a device capable of mdev_types sometime(for example:bind to proper driver) and incapable of mdev_types at other times(for example: unbind from its driver). We should keep the info of xml dumped out consistent with real status of the device. --- src/node_device/node_device_linux_sysfs.c | 42 +++++++++++++++++++++++++++++++ src/node_device/node_device_udev.c | 11 ++++++-- src/node_device/node_device_udev.h | 8 ++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c index 6f438e5..2dc01bf 100644 --- a/src/node_device/node_device_linux_sysfs.c +++ b/src/node_device/node_device_linux_sysfs.c @@ -29,6 +29,7 @@ #include "dirname.h" #include "node_device_driver.h" #include "node_device_hal.h" +#include "node_device_udev.h" #include "node_device_linux_sysfs.h" #include "virerror.h" #include "viralloc.h" @@ -175,6 +176,45 @@ nodeDeviceSysfsGetPCIIOMMUGroupCaps(virNodeDevCapPCIDevPtr pci_dev) return ret; } +static int +nodeDeviceSysfsGetPCIMdevTypesCaps(const char *sysfsPath, + virNodeDevCapPCIDevPtr pci_dev) +{ + size_t i; + int ret = -1; + struct udev *udev = NULL; + struct udev_device *device = NULL; + + /* this could be a refresh, so clear out the old data */ + for (i = 0; i < pci_dev->nmdev_types; i++) + VIR_FREE(pci_dev->mdev_types[i]); + VIR_FREE(pci_dev->mdev_types); + pci_dev->nmdev_types = 0; + + udev = udev_new(); + if (!udev) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to create udev context")); + goto cleanup; + } + device = udev_device_new_from_syspath(udev, sysfsPath); + if (!device) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to create udev device from path %s"), + sysfsPath); + goto cleanup; + } + + if (udevPCIGetMdevTypesCap(device, pci_dev) < 0) + goto cleanup; + + ret = 0; + cleanup: + udev_device_unref(device); + udev_unref(udev); + return ret; +} + /* nodeDeviceSysfsGetPCIRelatedCaps() get info that is stored in sysfs * about devices related to this device, i.e. things that can change @@ -190,6 +230,8 @@ nodeDeviceSysfsGetPCIRelatedDevCaps(const char *sysfsPath, return -1; if (nodeDeviceSysfsGetPCIIOMMUGroupCaps(pci_dev) < 0) return -1; + if (nodeDeviceSysfsGetPCIMdevTypesCaps(sysfsPath, pci_dev) < 0) + return -1; return 0; } diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index 1e1b717..256bb66 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -432,7 +432,7 @@ udevFillMdevType(struct udev_device *device, } -static int +int udevPCIGetMdevTypesCap(struct udev_device *device, virNodeDevCapPCIDevPtr pcidata) { @@ -599,8 +599,15 @@ udevProcessPCI(struct udev_device *device, /* check whether the device is mediated devices framework capable, if so, * process it + * + * UDEV doesn't report attributes under subdirectories by default but is + * able to query them if the path to the attribute is relative to the + * device's base path, e.g. /sys/devices/../0000:00:01.0/ is the device's + * base path as udev reports it, but we're interested in attributes under + * /sys/devices/../0000:00:01.0/mdev_supported_types/<type>/. So, we need to + * scan the subdirectories ourselves. */ - if (udevPCIGetMdevTypesCap(device, pci_dev) < 0) + if (udevPCIGetMdevTypesCap(udev_device_get_syspath(device), pci_dev) < 0) goto cleanup; ret = 0; diff --git a/src/node_device/node_device_udev.h b/src/node_device/node_device_udev.h index f15e520..9f78289 100644 --- a/src/node_device/node_device_udev.h +++ b/src/node_device/node_device_udev.h @@ -19,6 +19,8 @@ * * Author: Dave Allan <dallan@xxxxxxxxxx> */ +#ifndef __VIR_NODE_DEVICE_UDEV_H__ +#define __VIR_NODE_DEVICE_UDEV_H__ #include <libudev.h> #include <stdint.h> @@ -26,3 +28,9 @@ #define SYSFS_DATA_SIZE 4096 #define DMI_DEVPATH "/sys/devices/virtual/dmi/id" #define DMI_DEVPATH_FALLBACK "/sys/class/dmi/id" + +int +udevPCIGetMdevTypesCap(struct udev_device *device, virNodeDevCapPCIDevPtr pcidata); + + +#endif /* __VIR_NODE_DEVICE_UDEV_H__ */ -- 1.9.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list