tell_host() and stats_handle_request() both ignore the return value of
virtqueue_add_outbuf() and go on to kick the queue. The comment claims
"We should always be able to add one buffer to an empty queue", but that
does not hold once the virtqueue has been broken (e.g. on device
shutdown), where the add fails with -EIO.

In tell_host() the following wait_event() would then block forever on a
buffer the host can never return. stats_handle_request() does not
wait_event() afterwards so it cannot hang, but it still kicks a queue
with nothing queued.

Warn and bail out on failure in both, mirroring
virtballoon_free_page_report().

Suggested-by: David Hildenbrand <[email protected]>
Signed-off-by: Denis V. Lunev <[email protected]>
---
 drivers/virtio/virtio_balloon.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index d6106ccecf71..56c652555663 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -185,16 +185,18 @@ static void tell_host(struct virtio_balloon *vb, struct 
virtqueue *vq)
 {
        struct scatterlist sg;
        unsigned int len;
+       int err;
 
        sg_init_one(&sg, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns);
 
        /* We should always be able to add one buffer to an empty queue. */
-       virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL);
+       err = virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL);
+       if (WARN_ON_ONCE(err))
+               return;
        virtqueue_kick(vq);
 
        /* When host has read buffer, this completes via balloon_ack */
        wait_event(vb->acked, virtqueue_get_buf(vq, &len));
-
 }
 
 static int virtballoon_free_page_report(struct page_reporting_dev_info 
*pr_dev_info,
@@ -449,6 +451,7 @@ static void stats_handle_request(struct virtio_balloon *vb)
        struct virtqueue *vq;
        struct scatterlist sg;
        unsigned int len, num_stats;
+       int err;
 
        num_stats = update_balloon_stats(vb);
 
@@ -456,7 +459,9 @@ static void stats_handle_request(struct virtio_balloon *vb)
        if (!virtqueue_get_buf(vq, &len))
                return;
        sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats);
-       virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL);
+       err = virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL);
+       if (WARN_ON_ONCE(err))
+               return;
        virtqueue_kick(vq);
 }
 
-- 
2.53.0

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to