]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
nodedev: cache parent address in mdev caps
authorJonathon Jongsma <jjongsma@redhat.com>
Fri, 16 Jul 2021 18:15:54 +0000 (13:15 -0500)
committerJonathon Jongsma <jjongsma@redhat.com>
Fri, 6 Aug 2021 20:02:29 +0000 (15:02 -0500)
mdevctl can report multiple defined devices with the same UUID
but different parents, including parents that don't actually exist on
the host machine. Libvirt sets the parent to the 'computer' device for
all of the mdevs that have nonexistent parents. Because of this, it's
possible that there are multiple devices with the same UUID and the same
'computer' device as their parent, so the combination of uuid and parent
nodedev name is not guaranteed to be a unique name.

We need to ensure that each nodedev has a unique name. If we can't use
the UUID as a unique nodedev name, and we can't use the combination of
UUID and nodedev parent name, we need to find another solution. By
caching and using the parent name reported by mdevctl in combination
with the UUID, we can achieve a unique name. mdevctl guarantees that its
uuid/parent combination is unique.

This value will be used to set the mdev nodedev name in a following commit.

Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/conf/node_device_conf.c
src/conf/node_device_conf.h
src/node_device/node_device_driver.c
src/node_device/node_device_udev.c

index d12d97f0773d97c85ee6ecc94b44f5bdc08d3dc8..12ef18dc157d6d1ae36978a8a96f8bae755d99cf 100644 (file)
@@ -2309,6 +2309,7 @@ virNodeDevCapsDefFree(virNodeDevCapsDef *caps)
         for (i = 0; i < data->mdev.nattributes; i++)
             virMediatedDeviceAttrFree(data->mdev.attributes[i]);
         g_free(data->mdev.attributes);
+        g_free(data->mdev.parent_addr);
         break;
     case VIR_NODE_DEV_CAP_CSS_DEV:
         for (i = 0; i < data->ccw_dev.nmdev_types; i++)
index a60562e4fe63cb0c12a6c349eb4f94f909b07217..556878b9a8ff2ca210f7d42aae66370bac095417 100644 (file)
@@ -153,6 +153,7 @@ struct _virNodeDevCapMdev {
     char *uuid;
     virMediatedDeviceAttr **attributes;
     size_t nattributes;
+    char *parent_addr;
 };
 
 typedef struct _virNodeDevCapPCIDev virNodeDevCapPCIDev;
index 6820ec413bfc1c21047328b723904ef6bdcb68d9..daeaa084bd8b8f430c32ddc93dfbf8ed0ebffa67 100644 (file)
@@ -1088,6 +1088,7 @@ nodeDeviceParseMdevctlChildDevice(const char *parent,
 
     mdev = &child->caps->data.mdev;
     mdev->uuid = g_strdup(uuid);
+    mdev->parent_addr = g_strdup(parent);
     mdev->type =
         g_strdup(virJSONValueObjectGetString(props, "mdev_type"));
 
index f99578414d2a6b022137b6a0c8873cc6b59c2659..e7db74b325d726cc6378a07bc386ba0769d866ae 100644 (file)
@@ -1024,6 +1024,7 @@ udevProcessMediatedDevice(struct udev_device *dev,
     char *linkpath = NULL;
     char *canonicalpath = NULL;
     virNodeDevCapMdev *data = &def->caps->data.mdev;
+    struct udev_device *parent_device = NULL;
 
     /* Because of a kernel uevent race, we might get the 'add' event prior to
      * the sysfs tree being ready, so any attempt to access any sysfs attribute
@@ -1051,6 +1052,21 @@ udevProcessMediatedDevice(struct udev_device *dev,
     if ((iommugrp = virMediatedDeviceGetIOMMUGroupNum(data->uuid)) < 0)
         goto cleanup;
 
+    /* lookup the address of parent device */
+    parent_device = udev_device_get_parent(dev);
+    if (parent_device) {
+        const char *parent_sysfs_path = udev_device_get_syspath(parent_device);
+        if (parent_sysfs_path)
+            data->parent_addr = g_path_get_basename(parent_sysfs_path);
+    }
+
+    if (!data->parent_addr) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Could not get parent of '%s'"),
+                       udev_device_get_syspath(dev));
+        return -1;
+    }
+
     udevGenerateDeviceName(dev, def, NULL);
 
     data->iommuGroupNumber = iommugrp;