Both virtio_gpu_queue_ctrl_buffer and virtio_gpu_queue_cursor use virtqueue_add_sgs to upload the structure virtio_gpu_vbuffer * vbuf to virtqueue. However, when the vbuf fails to upload and virtqueue_add_sgs returns -EIO or -ENOMEM, the vbuf will not be able to be free by virtio_gpu_dequeue_*_func, resulting in a continuous increase in memory allocated to vgdev ->vbufs. Therefore, make virtio_gpu_queue_ctrl_sgs and virtio_gpu_queue_cursor free vbuf directly after virtqueue_add_sgs returns -EIO or -ENOMEM. Signed-off-by: Weishi Li <liweishi@xxxxxxxxxx> --- drivers/gpu/drm/virtio/virtgpu_vq.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index b1a00c0c25a7..6701ce9d0ee8 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -356,12 +356,14 @@ static int virtio_gpu_queue_ctrl_sgs(struct virtio_gpu_device *vgdev, ret = virtqueue_add_sgs(vq, sgs, outcnt, incnt, vbuf, GFP_ATOMIC); WARN_ON(ret); + if (ret < 0 && ret != -ENOSPC) { + free_vbuf(vgdev, vbuf); + } else { + vbuf->seqno = ++vgdev->ctrlq.seqno; + trace_virtio_gpu_cmd_queue(vq, virtio_gpu_vbuf_ctrl_hdr(vbuf), vbuf->seqno); - vbuf->seqno = ++vgdev->ctrlq.seqno; - trace_virtio_gpu_cmd_queue(vq, virtio_gpu_vbuf_ctrl_hdr(vbuf), vbuf->seqno); - - atomic_inc(&vgdev->pending_commands); - + atomic_inc(&vgdev->pending_commands); + } spin_unlock(&vgdev->ctrlq.qlock); drm_dev_exit(idx); @@ -469,6 +471,9 @@ static void virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev, wait_event(vgdev->cursorq.ack_queue, vq->num_free >= outcnt); spin_lock(&vgdev->cursorq.qlock); goto retry; + } else if (ret < 0) { + free_vbuf(vgdev, vbuf); + notify = false; } else { vbuf->seqno = ++vgdev->cursorq.seqno; trace_virtio_gpu_cmd_queue(vq, -- 2.25.1