Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx>
---
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);