> 21.05.2026 05:19, Ryosuke Yasuoka пишет:
>> virtio_gpu_queue_ctrl_sgs() and virtio_gpu_queue_cursor() use
>> wait_event() without any abort condition when waiting for virtqueue
>> space. If the host device stops processing commands, these waits block
>> indefinitely inside a drm_dev_enter/exit() critical section. Since
>> drm_dev_unplug(), which is called in device removal and system shutdown
>> call path, blocks on synchronize_srcu() until all critical sections
>> complete, device removal and system shutdown also hang.
>> 
>> Add a vqs_released flag to virtio_gpu_device and include it in the
>> wait_event() condition. Set the flag and wake up both queues in a new
>> virtio_gpu_release_vqs() helper, called before drm_dev_unplug() in both
>> virtio_gpu_remove() and virtio_gpu_shutdown(). When the flag is set, the
>> wait returns immediately and the command is aborted, following the same
>> cleanup path as drm_dev_enter() failure.
>> 
>> Reported-by: 
>> syzbot+d6dd6f86d3aaf7eebe7406e45c1c6e549453f...@syzkaller.appspotmail.com
>> Closes: 
>> https://syzkaller.appspot.com/bug?id=d6dd6f86d3aaf7eebe7406e45c1c6e549453f224
>> Reported-by: 
>> syzbot+908bd910da5dd79b88de4cf7baf376cc873a9...@syzkaller.appspotmail.com
>> Closes: 
>> https://syzkaller.appspot.com/bug?id=908bd910da5dd79b88de4cf7baf376cc873a922e
>> Signed-off-by: Ryosuke Yasuoka <[email protected]>
>> ---
>> Changes in v2:
>> - Update the commit message.
>> - Replace wait_event_timeout() with wait_event() using a compound
>> condition that includes a new vqs_released flag.
>> - Add virtio_gpu_release_vqs() helper to set the flag and wake up
>> both queues, called before drm_dev_unplug() in remove and shutdown
>> paths.
>> - Remove the hardcoded 5-second timeout. Recovery is now driven by
>> the driver flag instead of an arbitrary timeout value.
>> ---
>>  drivers/gpu/drm/virtio/virtgpu_drv.c | 15 +++++++++++++++
>>  drivers/gpu/drm/virtio/virtgpu_drv.h |  1 +
>>  drivers/gpu/drm/virtio/virtgpu_vq.c  | 23 +++++++++++++++++++++--
>>  3 files changed, 37 insertions(+), 2 deletions(-)
>> 
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c 
>> b/drivers/gpu/drm/virtio/virtgpu_drv.c
>> index a5ce96fb8a1d..e4fe5e0780f9 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_drv.c
>> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
>> @@ -119,10 +119,24 @@ static int virtio_gpu_probe(struct virtio_device *vdev)
>>      return ret;
>>  }
>>  
>> +/*
>> + * Release pending virtqueue waits so the drm_dev_enter/exit() critical
>> + * sections complete before drm_dev_unplug() blocks on synchronize_srcu().
>> + */
>> +static void virtio_gpu_release_vqs(struct drm_device *dev)
>> +{
>> +    struct virtio_gpu_device *vgdev = dev->dev_private;
>> +
>> +    vgdev->vqs_released = true;
>> +    wake_up_all(&vgdev->ctrlq.ack_queue);
>> +    wake_up_all(&vgdev->cursorq.ack_queue);
>> +}
>> +
>>  static void virtio_gpu_remove(struct virtio_device *vdev)
>>  {
>>      struct drm_device *dev = vdev->priv;
>>  
>> +    virtio_gpu_release_vqs(dev);
>>      drm_dev_unplug(dev);
>>      drm_atomic_helper_shutdown(dev);
>>      virtio_gpu_deinit(dev);
>> @@ -133,6 +147,7 @@ static void virtio_gpu_shutdown(struct virtio_device 
>> *vdev)
>>  {
>>      struct drm_device *dev = vdev->priv;
>>  
>> +    virtio_gpu_release_vqs(dev);
>>      /* stop talking to the device */
>>      drm_dev_unplug(dev);
>>  }
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h 
>> b/drivers/gpu/drm/virtio/virtgpu_drv.h
>> index f17660a71a3e..0bd69a40857e 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
>> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
>> @@ -235,6 +235,7 @@ struct virtio_gpu_device {
>>  
>>      struct virtio_gpu_queue ctrlq;
>>      struct virtio_gpu_queue cursorq;
>> +    bool vqs_released;
>>      struct kmem_cache *vbufs;
>>  
>>      atomic_t pending_commands;
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c 
>> b/drivers/gpu/drm/virtio/virtgpu_vq.c
>> index 67865810a2e7..8057a9b7356d 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_vq.c
>> +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
>> @@ -396,7 +396,19 @@ static int virtio_gpu_queue_ctrl_sgs(struct 
>> virtio_gpu_device *vgdev,
>>      if (vq->num_free < elemcnt) {
>>              spin_unlock(&vgdev->ctrlq.qlock);
>>              virtio_gpu_notify(vgdev);
>> -            wait_event(vgdev->ctrlq.ack_queue, vq->num_free >= elemcnt);
>> +            wait_event(vgdev->ctrlq.ack_queue,
>> +                       vq->num_free >= elemcnt || vgdev->vqs_released);
>> +            /*
>> +             * Set by virtio_gpu_release_vqs() to unblock
>> +             * synchronize_srcu() wait in drm_dev_unplug().
>> +             */
>> +            if (vgdev->vqs_released) {
>> +                    if (fence && vbuf->objs)
>> +                            virtio_gpu_array_unlock_resv(vbuf->objs);
>> +                    free_vbuf(vgdev, vbuf);
>> +                    drm_dev_exit(idx);
>> +                    return -ENODEV;
>> +            }
>>              goto again;
>>      }
>>  
>> @@ -566,7 +578,14 @@ static void virtio_gpu_queue_cursor(struct 
>> virtio_gpu_device *vgdev,
>>      ret = virtqueue_add_sgs(vq, sgs, outcnt, 0, vbuf, GFP_ATOMIC);
>>      if (ret == -ENOSPC) {
>>              spin_unlock(&vgdev->cursorq.qlock);
>> -            wait_event(vgdev->cursorq.ack_queue, vq->num_free >= outcnt);
>> +            wait_event(vgdev->cursorq.ack_queue,
>> +                       vq->num_free >= outcnt || vgdev->vqs_released);
>> +            /* See comment in virtio_gpu_queue_ctrl_sgs(). */
>> +            if (vgdev->vqs_released) {
>> +                    free_vbuf(vgdev, vbuf);
>> +                    drm_dev_exit(idx);
>> +                    return;
>> +            }
>>              spin_lock(&vgdev->cursorq.qlock);
>>              goto retry;
>>      } else {
>
> What about other wait_event in the driver? Why only these?
>
> -- 
> Best regards,
> Dmitry

I see the command but can't find the corresponding bug.
The email is sent to  [email protected] address
but the HASH does not correspond to any known bug.
Please double check the address.


Reply via email to