On Thu, Dec 24, 2020 at 08:14:31AM -0600, Jonathon Jongsma wrote: > At startup, query devices that are defined by 'mdevctl' and add them to > the node device list. > > This adds a complication: we now have two potential sources of > information for a node device: > - udev for all devices and for activated mediated devices > - mdevctl for persistent mediated devices > > Unfortunately, neither backend returns full information for a mediated > device. For example, if a persistent mediated device in the list (with > information provided from mdevctl) is 'started', that same device will > now be detected by udev. If we simply overwrite the existing device > definition with the new one provided by the udev backend, we will lose > extra information that was provided by mdevctl (e.g. attributes, etc). > To avoid this, make sure to copy the extra information into the new > device definition. > > Signed-off-by: Jonathon Jongsma <jjongsma@xxxxxxxxxx> > --- > src/node_device/node_device_driver.c | 76 ++++++++++++++++++++++++++++ > src/node_device/node_device_driver.h | 3 ++ > src/node_device/node_device_udev.c | 48 ++++++++++++++++++ > 3 files changed, 127 insertions(+) > > diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c > index 5309b8abd5..0267005af1 100644 > --- a/src/node_device/node_device_driver.c > +++ b/src/node_device/node_device_driver.c > @@ -1144,3 +1144,79 @@ nodeDeviceGenerateName(virNodeDeviceDefPtr def, > *(def->name + i) = '_'; > } > } > + > + > +static int > +virMdevctlListDefined(virNodeDeviceDefPtr **devs) > +{ > + int status; > + g_autofree char *output = NULL; > + g_autoptr(virCommand) cmd = nodeDeviceGetMdevctlListCommand(true, &output); > + > + if (virCommandRun(cmd, &status) < 0) > + return -1; > + > + if (!output) > + return -1; > + > + return nodeDeviceParseMdevctlJSON(output, devs); > +} > + > + > +int > +nodeDeviceUpdateMediatedDevices(void) > +{ > + g_autofree virNodeDeviceDefPtr *devs = NULL; > + int ndevs; > + size_t i; > + > + if ((ndevs = virMdevctlListDefined(&devs)) < 0) { > + virReportSystemError(errno, "%s", > + _("failed to query mdevs from mdevctl")); > + return -1; > + } > + > + for (i = 0; i < ndevs; i++) { > + virNodeDeviceObjPtr obj; > + virObjectEventPtr event; > + virNodeDeviceDefPtr dev = devs[i]; > + bool new_device = true; > + > + dev->driver = g_strdup("vfio_mdev"); > + > + /* If a device defined by mdevctl is already in the list, that means > + * that it was found via the normal device discovery process and thus > + * is already activated. Active devices contain some additional > + * information (e.g. sysfs path) that is not provided by mdevctl, so > + * preserve that info */ > + if ((obj = virNodeDeviceObjListFindByName(driver->devs, dev->name))) { > + virNodeDeviceDefPtr olddef = virNodeDeviceObjGetDef(obj); > + > + /* Copy any data from the existing device */ > + dev->sysfs_path = g_strdup(olddef->sysfs_path); > + dev->parent_sysfs_path = g_strdup(olddef->parent_sysfs_path); > + dev->driver = g_strdup(olddef->driver); > + dev->devnode = g_strdup(olddef->devnode); > + dev->caps->data.mdev.iommuGroupNumber = olddef->caps->data.mdev.iommuGroupNumber; > + > + virNodeDeviceObjEndAPI(&obj); > + new_device = false; > + } > + > + if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, dev))) { > + virNodeDeviceDefFree(dev); > + return -1; > + } > + > + if (new_device) > + event = virNodeDeviceEventLifecycleNew(dev->name, > + VIR_NODE_DEVICE_EVENT_CREATED, > + 0); As mentioned in the other patch, we need to have DEFINED/UNDEFINED events. In fact this method doens't seem to remove existing mdevs that no longer exist. > + else > + event = virNodeDeviceEventUpdateNew(dev->name); This is triggering events for all devices every time any single device changes, even if those devices have no changes. Regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|