[PATCH] drm/virtio: reclaim pending vbufs before tearing down vqs
From: Anuj Bolewar via B4 Relay <devnull+bolewara.gmail.com@kernel.org>
Date: 2026-08-02 15:15:46
Also in:
b4-sent, dri-devel, lkml
Subsystem:
drm drivers, drm drivers and misc gpu patches, the rest, virtio gpu driver · Maintainers:
David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Linus Torvalds, David Airlie, Gerd Hoffmann, Dmitry Osipenko
From: Anuj Bolewar <redacted>
virtio_gpu_free_vbufs() destroys the vbufs kmem_cache after the virtqueues
have already been released. Commands that were queued but never completed
by the device leave their vbuffers stranded in the virtqueue, so the cache
still holds live objects when virtio_gpu_deinit() tears everything down.
This triggers a WARNING in virtio_gpu_free_vbufs:
BUG virtio-gpu-vbufs (Not tainted): Objects remaining in cache
on __kmem_cache_shutdown()
Drain any buffers still sitting in the control and cursor virtqueues in
virtio_gpu_deinit() after the device has been reset and before the
virtqueues are deleted, following the same pattern used by virtio_console's
remove_vqs(). Each reclaimed buffer is released with free_vbuf(), dropping
the reference on any GEM objects it holds.
Reported-by: syzbot+06f9b2a53ba4a5a47644@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=06f9b2a53ba4a5a47644
Signed-off-by: Anuj Bolewar <redacted>
---
drivers/gpu/drm/virtio/virtgpu_drv.h | 1 +
drivers/gpu/drm/virtio/virtgpu_kms.c | 1 +
drivers/gpu/drm/virtio/virtgpu_vq.c | 13 +++++++++++++
3 files changed, 15 insertions(+)
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 7449907754a..3e491c80873 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h@@ -332,6 +332,7 @@ void virtio_gpu_array_put_free_work(struct work_struct *work); /* virtgpu_vq.c */ int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev); void virtio_gpu_free_vbufs(struct virtio_gpu_device *vgdev); +void virtio_gpu_reclaim_vbufs(struct virtio_gpu_device *vgdev); void virtio_gpu_cmd_create_resource(struct virtio_gpu_device *vgdev, struct virtio_gpu_object *bo, struct virtio_gpu_object_params *params,
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index b4329f28e97..e5a6ae679f3 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c@@ -298,6 +298,7 @@ void virtio_gpu_deinit(struct drm_device *dev) flush_work(&vgdev->cursorq.dequeue_work); flush_work(&vgdev->config_changed_work); virtio_reset_device(vgdev->vdev); + virtio_gpu_reclaim_vbufs(vgdev); vgdev->vdev->config->del_vqs(vgdev->vdev); }
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index e5e1af8b8e8..95d7a9ef0d9 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c@@ -208,6 +208,19 @@ static void free_vbuf(struct virtio_gpu_device *vgdev, kmem_cache_free(vgdev->vbufs, vbuf); } +void virtio_gpu_reclaim_vbufs(struct virtio_gpu_device *vgdev) +{ + struct virtio_gpu_vbuffer *vbuf; + + while ((vbuf = virtqueue_detach_unused_buf(vgdev->ctrlq.vq))) { + if (vbuf->objs) + virtio_gpu_array_put_free(vbuf->objs); + free_vbuf(vgdev, vbuf); + } + while ((vbuf = virtqueue_detach_unused_buf(vgdev->cursorq.vq))) + free_vbuf(vgdev, vbuf); +} + static void reclaim_vbufs(struct virtqueue *vq, struct list_head *reclaim_list) { struct virtio_gpu_vbuffer *vbuf;
--- base-commit: 2d2338c93da79b3bfe4b6099a931d9468d539952 change-id: 20260802-virtio-gpu-reclaim-vbufs-4816cc8a5bf9 Best regards, -- Anuj Bolewar [off-list ref]