[libvirt] [PATCH v1 05/31] virpcimock: Create driver_override file in device dirs
Michal Privoznik
mprivozn at redhat.com
Tue Jul 16 14:37:11 UTC 2019
On 7/16/19 2:13 PM, Peter Krempa wrote:
> On Thu, Jul 11, 2019 at 17:53:52 +0200, Michal Privoznik wrote:
>> Newer kernels (v3.16-rc1~29^2~6^4) have 'driver_override' file
>> which simplifies way of binding a PCI device to desired driver.
>> Libvirt has support for this for some time too (v2.3.0-rc1~236),
>> but not our virpcimock. So far we did not care because our code
>> is designed to deal with this situation. Except for one.
>> hypothetical case: binding a device to the vfio-pci driver can be
>> successful only via driver_override. Any attempt to bind a PCI
>> device to vfio-pci driver using old method (new_id + unbind +
>> bind) will fail because of b803b29c1a5. While on vanilla kernel
>
> You've reverted the mentioned commit just before this patch.
Yep, I needed to do that s
>
> Also I did not understand what this is supposed to do from the commit
> message. Perhaps due to my limited understanding of the pci detachment
> code. So either somebody else reviews this or you'll need to reprhase
> the commit message.
>
>> I'm able to use the old method successfully, it's failing on RHEL
>> kernels (not sure why).
>
> This does not inspire confidence.
I've asked Alex Williamson about this and he confirmed that he can see
this behaviour but nor he could understand why RHEL-7 kernel behaves
that way.
>
>>
>> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>> ---
>> tests/virpcimock.c | 57 +++++++++++++++++++++++++++++++++++++++++-----
>> 1 file changed, 51 insertions(+), 6 deletions(-)
>>
>> diff --git a/tests/virpcimock.c b/tests/virpcimock.c
>> index 6865f992dc..18d06d11d4 100644
>> --- a/tests/virpcimock.c
>> +++ b/tests/virpcimock.c
>> @@ -87,6 +87,11 @@ char *fakesysfspcidir;
>> * Probe for a driver that handles the specified device.
>> * Data in format "DDDD:BB:DD.F" (Domain:Bus:Device.Function).
>> *
>> + * /sys/bus/pci/devices/<device>/driver_override
>> + * Name of a driver that overrides preferred driver can be written
>> + * here. The device will be attached to it on drivers_probe event.
>> + * Writing an empty string (or "\n") clears the override.
>> + *
>> * As a little hack, we are not mocking write to these files, but close()
>> * instead. The advantage is we don't need any self growing array to hold the
>> * partial writes and construct them back. We can let all the writes finish,
>> @@ -147,6 +152,7 @@ static struct pciDevice *pci_device_find_by_content(const char *path);
>> static void pci_driver_new(const char *name, int fail, ...);
>> static struct pciDriver *pci_driver_find_by_dev(struct pciDevice *dev);
>> static struct pciDriver *pci_driver_find_by_path(const char *path);
>> +static struct pciDriver *pci_driver_find_by_driver_override(struct pciDevice *dev);
>> static int pci_driver_bind(struct pciDriver *driver, struct pciDevice *dev);
>> static int pci_driver_unbind(struct pciDriver *driver, struct pciDevice *dev);
>> static int pci_driver_handle_change(int fd, const char *path);
>> @@ -202,7 +208,8 @@ make_symlink(const char *path,
>> static int
>> pci_read_file(const char *path,
>> char *buf,
>> - size_t buf_size)
>> + size_t buf_size,
>> + bool truncate)
>> {
>> int ret = -1;
>> int fd = -1;
>> @@ -224,7 +231,8 @@ pci_read_file(const char *path,
>> goto cleanup;
>> }
>>
>> - if (ftruncate(fd, 0) < 0)
>> + if (truncate &&
>> + ftruncate(fd, 0) < 0)
>> goto cleanup;
>>
>> ret = 0;
>> @@ -398,6 +406,8 @@ pci_device_new_from_stub(const struct pciDevice *data)
>> ABORT("@tmp overflow");
>> make_file(devpath, "class", tmp, -1);
>>
>> + make_file(devpath, "driver_override", NULL, -1);
>> +
>> if (snprintf(tmp, sizeof(tmp),
>> "%s/../../../kernel/iommu_groups/%d",
>> devpath, dev->iommuGroup) < 0) {
>> @@ -441,7 +451,7 @@ pci_device_find_by_content(const char *path)
>> {
>> char tmp[32];
>>
>> - if (pci_read_file(path, tmp, sizeof(tmp)) < 0)
>> + if (pci_read_file(path, tmp, sizeof(tmp), true) < 0)
>> return NULL;
>>
>> return pci_device_find_by_id(tmp);
>> @@ -450,7 +460,10 @@ pci_device_find_by_content(const char *path)
>> static int
>> pci_device_autobind(struct pciDevice *dev)
>> {
>> - struct pciDriver *driver = pci_driver_find_by_dev(dev);
>> + struct pciDriver *driver = pci_driver_find_by_driver_override(dev);
>> +
>> + if (!driver)
>> + driver = pci_driver_find_by_dev(dev);
This could explain why the check from 03/31 can't be here. If it was,
then nor 'driver_override' would be able to bind a PCI device to the
vfio-pci driver (which obviously is not the case).
>>
>> if (!driver) {
>> /* No driver found. Nothing to do */
>> @@ -544,6 +557,36 @@ pci_driver_find_by_path(const char *path)
>> return NULL;
>> }
>>
>> +static struct pciDriver *
>> +pci_driver_find_by_driver_override(struct pciDevice *dev)
>> +{
>> + struct pciDriver *ret = NULL;
>> + char *path = NULL;
>> + char tmp[32];
>> + size_t i;
>> +
>> + if (virAsprintfQuiet(&path,
>> + SYSFS_PCI_PREFIX "devices/%s/driver_override",
>> + dev->id) < 0)
>> + return NULL;
>> +
>> + if (pci_read_file(path, tmp, sizeof(tmp), false) < 0)
>> + goto cleanup;
>> +
>> + for (i = 0; i < nPCIDrivers; i++) {
>> + struct pciDriver *driver = pciDrivers[i];
>> +
>> + if (STREQ(tmp, driver->name)) {
>> + ret = driver;
>> + break;
>> + }
>> + }
>> +
>> + cleanup:
>> + VIR_FREE(path);
>
> VIR_AUTOFREE should be available.
Ah, good point. Consider fixed.
Michal
More information about the libvir-list
mailing list