Skip to content

Commit d1cae69

Browse files
Ming Leiming1
authored andcommitted
nvme_vfio: fix first vfio-pci bind failure by using driver_override
The old bind_vfio_pci() used new_id + bind to attach a device to vfio-pci. Writing to new_id triggers auto-probe which races with the subsequent bind write, causing EBUSY on the first attempt. The second attempt succeeds because setup_vfio_binding() sees the device already bound to vfio-pci from the auto-probe. Switch to driver_override + drivers_probe which is the recommended kernel mechanism for targeted device-driver binding: - No auto-probe race: drivers_probe is a single synchronous operation - Device-scoped: only affects the specific PCI device, not all devices with the same vendor:device ID - Simpler: no need to read vendor/device IDs from sysfs Signed-off-by: Ming Lei <ming.lei@redhat.com>
1 parent 204e5b3 commit d1cae69

1 file changed

Lines changed: 20 additions & 54 deletions

File tree

targets/nvme/ublk.nvme_vfio.cpp

Lines changed: 20 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -520,81 +520,47 @@ static int unbind_driver(const char *pci_addr)
520520
return 0;
521521
}
522522

523-
/* Bind device to vfio-pci driver */
523+
/*
524+
* Bind device to vfio-pci driver using driver_override.
525+
*
526+
* The driver_override approach is preferred over new_id + bind because
527+
* writing to new_id triggers auto-probe which races with the explicit
528+
* bind, causing EBUSY errors on the first attempt.
529+
*/
524530
static int bind_vfio_pci(const char *pci_addr)
525531
{
526-
char path[256], vendor[16], device[16];
527-
char vendor_device[32];
532+
char path[256];
528533
int fd;
529534

530-
/* Read vendor:device ID */
535+
/* Set driver_override to vfio-pci */
531536
snprintf(path, sizeof(path),
532-
"/sys/bus/pci/devices/%s/vendor", pci_addr);
533-
fd = open(path, O_RDONLY);
537+
"/sys/bus/pci/devices/%s/driver_override", pci_addr);
538+
fd = open(path, O_WRONLY);
534539
if (fd < 0) {
535-
ublk_err("open vendor: %s\n", strerror(errno));
540+
ublk_err("open driver_override: %s\n", strerror(errno));
536541
return -1;
537542
}
538-
if (read(fd, vendor, sizeof(vendor)) < 0) {
539-
ublk_err("read vendor: %s\n", strerror(errno));
543+
if (write(fd, "vfio-pci", 8) < 0) {
544+
ublk_err("write driver_override: %s\n", strerror(errno));
540545
close(fd);
541546
return -1;
542547
}
543548
close(fd);
544-
vendor[strcspn(vendor, "\n")] = 0;
545549

546-
snprintf(path, sizeof(path),
547-
"/sys/bus/pci/devices/%s/device", pci_addr);
548-
fd = open(path, O_RDONLY);
550+
/* Trigger driver probe for the device */
551+
fd = open("/sys/bus/pci/drivers_probe", O_WRONLY);
549552
if (fd < 0) {
550-
ublk_err("open device: %s\n", strerror(errno));
553+
ublk_err("open drivers_probe: %s\n", strerror(errno));
551554
return -1;
552555
}
553-
if (read(fd, device, sizeof(device)) < 0) {
554-
ublk_err("read device: %s\n", strerror(errno));
556+
if (write(fd, pci_addr, strlen(pci_addr)) < 0) {
557+
ublk_err("write drivers_probe: %s\n", strerror(errno));
555558
close(fd);
556559
return -1;
557560
}
558561
close(fd);
559-
device[strcspn(device, "\n")] = 0;
560-
561-
/* Remove 0x prefix and format as "vendor device" */
562-
snprintf(vendor_device, sizeof(vendor_device), "%s %s",
563-
vendor + 2, device + 2);
564-
565-
/* Add device ID to vfio-pci */
566-
fd = open("/sys/bus/pci/drivers/vfio-pci/new_id", O_WRONLY);
567-
if (fd < 0) {
568-
ublk_err("open new_id: %s\n", strerror(errno));
569-
return -1;
570-
}
571-
572-
if (write(fd, vendor_device, strlen(vendor_device)) < 0) {
573-
if (errno != EEXIST) {
574-
ublk_err("write new_id: %s\n", strerror(errno));
575-
close(fd);
576-
return -1;
577-
}
578-
}
579-
close(fd);
580-
581-
/* Explicitly bind the device */
582-
fd = open("/sys/bus/pci/drivers/vfio-pci/bind", O_WRONLY);
583-
if (fd < 0) {
584-
ublk_err("open vfio-pci bind: %s\n", strerror(errno));
585-
return -1;
586-
}
587-
588-
if (write(fd, pci_addr, strlen(pci_addr)) < 0) {
589-
if (errno != EEXIST) {
590-
ublk_err("bind to vfio-pci: %s\n", strerror(errno));
591-
close(fd);
592-
return -1;
593-
}
594-
}
595-
close(fd);
596562

597-
usleep(200000); /* 200ms delay */
563+
usleep(200000); /* 200ms for driver probe to complete */
598564

599565
return 0;
600566
}

0 commit comments

Comments
 (0)