From e44408dd9c45cb4f5e41caef4a9d2b7d2b8eb528 Mon Sep 17 00:00:00 2001 From: Jonathon Jongsma Date: Fri, 16 Jul 2021 13:15:54 -0500 Subject: [PATCH] nodedev: cache parent address in mdev caps 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 Reviewed-by: Michal Privoznik --- src/conf/node_device_conf.c | 1 + src/conf/node_device_conf.h | 1 + src/node_device/node_device_driver.c | 1 + src/node_device/node_device_udev.c | 16 ++++++++++++++++ 4 files changed, 19 insertions(+) diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index d12d97f077..12ef18dc15 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -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++) diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index a60562e4fe..556878b9a8 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -153,6 +153,7 @@ struct _virNodeDevCapMdev { char *uuid; virMediatedDeviceAttr **attributes; size_t nattributes; + char *parent_addr; }; typedef struct _virNodeDevCapPCIDev virNodeDevCapPCIDev; diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c index 6820ec413b..daeaa084bd 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -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")); diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index f99578414d..e7db74b325 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -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;