[libvirt PATCH v3 07/21] nodedev: add mdevctl devices to node device list

Daniel P. Berrangé berrange at redhat.com
Wed Jan 6 14:22:32 UTC 2021


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 at redhat.com>
> ---
>  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 :|




More information about the libvir-list mailing list