When a pasid entry becomes invalid, we need to release all resources
allocated for that entry including FAULTQ object and fault_fd.
We call qemu_set_fd_handler() to detach fault_fd's io_read handler and
wakes up main thread from poll(), but there could still be a small
window we call iommufd_backend_free_id(fault_id) before poll() exit
and release fault_id file reference. In this rare case, FAULTQ object
free return -EBUSY because opened fault_id file keeps reference of
FAULTQ object.
Teardown FAULTQ resources in bottom half to ensure poll() has released
fault_id file reference.
Suggested-by: Shameer Kolothum <skolothumtho@nvidia.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
---
hw/i386/intel_iommu_accel.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c
index 44af534c55..fdc376c070 100644
--- a/hw/i386/intel_iommu_accel.c
+++ b/hw/i386/intel_iommu_accel.c
@@ -267,16 +267,43 @@ free_faultq:
return false;
}
+typedef struct IOMMUFaultQueue {
+ IOMMUFDBackend *iommufd;
+ uint32_t id;
+ int fd;
+} IOMMUFaultQueue;
+
+static void faultq_teardown_bh(void *opaque)
+{
+ IOMMUFaultQueue *fq = opaque;
+
+ qemu_set_fd_handler(fq->fd, NULL, NULL, NULL);
+ close(fq->fd);
+ iommufd_backend_free_id(fq->iommufd, fq->id);
+
+ g_free(fq);
+}
+
+
static void vtd_destroy_old_fs_faultq(VTDHostIOMMUDevice *vtd_hiod,
VTDAccelPASIDCacheEntry *vtd_pce)
{
+ HostIOMMUDeviceIOMMUFD *idev = HOST_IOMMU_DEVICE_IOMMUFD(vtd_hiod->hiod);
+
if (!vtd_pce->fault_id) {
return;
}
vtd_pce->pri_notifier = NULL;
- qemu_set_fd_handler(vtd_pce->fault_fd, NULL, NULL, NULL);
- vtd_destroy_fs_faultq(vtd_hiod, vtd_pce->fault_id, vtd_pce->fault_fd);
+
+ IOMMUFaultQueue *fq = g_malloc(sizeof(IOMMUFaultQueue));
+ fq->iommufd = idev->iommufd;
+ fq->fd = vtd_pce->fault_fd;
+ fq->id = vtd_pce->fault_id;
+
+ aio_bh_schedule_oneshot(iohandler_get_aio_context(),
+ faultq_teardown_bh, fq);
+
vtd_pce->fault_id = 0;
vtd_pce->fault_fd = -1;
}
--
2.47.3