vfio: cleanup vfio_get_device error path, remove vfio_populate_device callback
Now that vfio_put_base_device is called unconditionally at instance_finalize time, it can be called twice if vfio_populate_device fails. This works but it is slightly harder to follow. Change vfio_get_device to not touch the vbasedev struct until it will definitely succeed, moving the vfio_populate_device call back to vfio-pci. This way, vfio_put_base_device will only be called once. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
parent
6e48e8f9e0
commit
217e9fdcad
@ -867,27 +867,28 @@ int vfio_get_device(VFIOGroup *group, const char *name,
|
|||||||
VFIODevice *vbasedev)
|
VFIODevice *vbasedev)
|
||||||
{
|
{
|
||||||
struct vfio_device_info dev_info = { .argsz = sizeof(dev_info) };
|
struct vfio_device_info dev_info = { .argsz = sizeof(dev_info) };
|
||||||
int ret;
|
int ret, fd;
|
||||||
|
|
||||||
ret = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, name);
|
fd = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, name);
|
||||||
if (ret < 0) {
|
if (fd < 0) {
|
||||||
error_report("vfio: error getting device %s from group %d: %m",
|
error_report("vfio: error getting device %s from group %d: %m",
|
||||||
name, group->groupid);
|
name, group->groupid);
|
||||||
error_printf("Verify all devices in group %d are bound to vfio-<bus> "
|
error_printf("Verify all devices in group %d are bound to vfio-<bus> "
|
||||||
"or pci-stub and not already in use\n", group->groupid);
|
"or pci-stub and not already in use\n", group->groupid);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ioctl(fd, VFIO_DEVICE_GET_INFO, &dev_info);
|
||||||
|
if (ret) {
|
||||||
|
error_report("vfio: error getting device info: %m");
|
||||||
|
close(fd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
vbasedev->fd = ret;
|
vbasedev->fd = fd;
|
||||||
vbasedev->group = group;
|
vbasedev->group = group;
|
||||||
QLIST_INSERT_HEAD(&group->device_list, vbasedev, next);
|
QLIST_INSERT_HEAD(&group->device_list, vbasedev, next);
|
||||||
|
|
||||||
ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_INFO, &dev_info);
|
|
||||||
if (ret) {
|
|
||||||
error_report("vfio: error getting device info: %m");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
vbasedev->num_irqs = dev_info.num_irqs;
|
vbasedev->num_irqs = dev_info.num_irqs;
|
||||||
vbasedev->num_regions = dev_info.num_regions;
|
vbasedev->num_regions = dev_info.num_regions;
|
||||||
vbasedev->flags = dev_info.flags;
|
vbasedev->flags = dev_info.flags;
|
||||||
@ -896,14 +897,7 @@ int vfio_get_device(VFIOGroup *group, const char *name,
|
|||||||
dev_info.num_irqs);
|
dev_info.num_irqs);
|
||||||
|
|
||||||
vbasedev->reset_works = !!(dev_info.flags & VFIO_DEVICE_FLAGS_RESET);
|
vbasedev->reset_works = !!(dev_info.flags & VFIO_DEVICE_FLAGS_RESET);
|
||||||
|
return 0;
|
||||||
ret = vbasedev->ops->vfio_populate_device(vbasedev);
|
|
||||||
|
|
||||||
error:
|
|
||||||
if (ret) {
|
|
||||||
vfio_put_base_device(vbasedev);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vfio_put_base_device(VFIODevice *vbasedev)
|
void vfio_put_base_device(VFIODevice *vbasedev)
|
||||||
|
@ -195,7 +195,6 @@ static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
|
|||||||
static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
|
static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
|
||||||
uint32_t val, int len);
|
uint32_t val, int len);
|
||||||
static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled);
|
static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled);
|
||||||
static int vfio_populate_device(VFIODevice *vbasedev);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disabling BAR mmaping can be slow, but toggling it around INTx can
|
* Disabling BAR mmaping can be slow, but toggling it around INTx can
|
||||||
@ -2934,12 +2933,11 @@ static VFIODeviceOps vfio_pci_ops = {
|
|||||||
.vfio_compute_needs_reset = vfio_pci_compute_needs_reset,
|
.vfio_compute_needs_reset = vfio_pci_compute_needs_reset,
|
||||||
.vfio_hot_reset_multi = vfio_pci_hot_reset_multi,
|
.vfio_hot_reset_multi = vfio_pci_hot_reset_multi,
|
||||||
.vfio_eoi = vfio_eoi,
|
.vfio_eoi = vfio_eoi,
|
||||||
.vfio_populate_device = vfio_populate_device,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int vfio_populate_device(VFIODevice *vbasedev)
|
static int vfio_populate_device(VFIOPCIDevice *vdev)
|
||||||
{
|
{
|
||||||
VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
|
VFIODevice *vbasedev = &vdev->vbasedev;
|
||||||
struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
|
struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
|
||||||
struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) };
|
struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) };
|
||||||
int i, ret = -1;
|
int i, ret = -1;
|
||||||
@ -3248,6 +3246,11 @@ static int vfio_initfn(PCIDevice *pdev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = vfio_populate_device(vdev);
|
||||||
|
if (ret) {
|
||||||
|
goto out_put;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get a copy of config space */
|
/* Get a copy of config space */
|
||||||
ret = pread(vdev->vbasedev.fd, vdev->pdev.config,
|
ret = pread(vdev->vbasedev.fd, vdev->pdev.config,
|
||||||
MIN(pci_config_size(&vdev->pdev), vdev->config_size),
|
MIN(pci_config_size(&vdev->pdev), vdev->config_size),
|
||||||
|
@ -112,7 +112,6 @@ struct VFIODeviceOps {
|
|||||||
void (*vfio_compute_needs_reset)(VFIODevice *vdev);
|
void (*vfio_compute_needs_reset)(VFIODevice *vdev);
|
||||||
int (*vfio_hot_reset_multi)(VFIODevice *vdev);
|
int (*vfio_hot_reset_multi)(VFIODevice *vdev);
|
||||||
void (*vfio_eoi)(VFIODevice *vdev);
|
void (*vfio_eoi)(VFIODevice *vdev);
|
||||||
int (*vfio_populate_device)(VFIODevice *vdev);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct VFIOGroup {
|
typedef struct VFIOGroup {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user