On Wed, 2026-09-16 at 18:04 +0800, Zhenzhong Duan wrote:
> Caution: External email. Do not open attachments or click links, unless this 
> email comes from a known sender and you know the content is safe.
> 
> 
> 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 
> <[[email protected]](mailto:[email protected])>  
> Signed-off-by: Zhenzhong Duan 
> <[[email protected]](mailto:[email protected])>  
> Tested-by: Xudong Hao <[[email protected]](mailto:[email protected])>  
> ---  
>  hw/i386/intel_iommu_accel.c | 40 ++++++++++++++++++++++++++++++++++---  
>  1 file changed, 37 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/i386/intel_iommu_accel.c b/hw/i386/intel_iommu_accel.c  
> index cd227315da..c3f3c74482 100644  
> --- a/hw/i386/intel_iommu_accel.c  
> +++ b/hw/i386/intel_iommu_accel.c  
> @@ -268,17 +268,51 @@ free_faultq:  
>      return false;  
>  }
> 
> +typedef struct IOMMUFaultQueue {  
> +    IOMMUFDBackend *iommufd;  
> +    uint32_t id;  
> +    int fd;  
> +    QLIST_HEAD(, VTDPRQEntry) vtd_prq_list;  
> +} IOMMUFaultQueue;  
> +  
> +static void faultq_teardown_bh(void *opaque)  
> +{  
> +    IOMMUFaultQueue *fq = opaque;  
> +    VTDPRQEntry *prqe, *next;  
> +  
> +    QLIST_FOREACH_SAFE(prqe, &fq->vtd_prq_list, next, next) {  
> +        QLIST_REMOVE(prqe, next);  
> +        g_free(prqe);  
> +    }  
> +  
> +    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(VTDAccelPASIDCacheEntry *vtd_pce)  
>  {  
> +    HostIOMMUDeviceIOMMUFD *idev =  
> +        HOST_IOMMU_DEVICE_IOMMUFD(vtd_pce->vtd_hiod->hiod);  
> +    IOMMUFaultQueue *fq;  
> +  
>      if (vtd_pce->fault_fd < 0) {  
>          return;  
>      }
> 
> -    qemu_set_fd_handler(vtd_pce->fault_fd, NULL, NULL, NULL);  
> -    vtd_destroy_fs_faultq(vtd_pce->vtd_hiod, vtd_pce->fault_id,  
> -                          vtd_pce->fault_fd);  
> +    fq = g_malloc(sizeof(IOMMUFaultQueue));  

sizeof(*fq)

> +    fq->iommufd = idev->iommufd;  
> +    fq->fd = vtd_pce->fault_fd;  
> +    fq->id = vtd_pce->fault_id;  
>      vtd_pce->fault_id = 0;  
>      vtd_pce->fault_fd = -1;  
> +    fq->vtd_prq_list.lh_first = vtd_pce->vtd_prq_list.lh_first;  
> +    QLIST_INIT(&vtd_pce->vtd_prq_list);  

are we sure that vtd_pce->vtd_prq_list is not updated by another thread 
concurrently at this point?

> +  
> +    aio_bh_schedule_oneshot(iohandler_get_aio_context(),  
> +                            faultq_teardown_bh, fq);  
>  }
> 
>  static void vtd_setup_fs_faultq(VTDAccelPASIDCacheEntry *vtd_pce,  
> --  
> 2.52.0
> 

Reply via email to