diff options
author | Wolfgang Bumiller <w.bumiller@proxmox.com> | 2017-09-20 08:09:33 +0200 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2017-10-15 05:54:44 +0300 |
commit | 37ef70be6af7e9f2a6f852c68f74bd98dac2664b (patch) | |
tree | 827770663eae17214eeb785fc21a315e8a70d759 /hw/virtio/virtio.c | |
parent | 8e36c336d943c3bfe0d06f5465cc64d44b306e13 (diff) | |
download | qemu-37ef70be6af7e9f2a6f852c68f74bd98dac2664b.zip qemu-37ef70be6af7e9f2a6f852c68f74bd98dac2664b.tar.gz qemu-37ef70be6af7e9f2a6f852c68f74bd98dac2664b.tar.bz2 |
virtio: fix descriptor counting in virtqueue_pop
While changing the s/g list allocation, commit 3b3b0628
also changed the descriptor counting to count iovec entries
as split by cpu_physical_memory_map(). Previously only the
actual descriptor entries were counted and the split into
the iovec happened afterwards in virtqueue_map().
Count the entries again instead to avoid erroneous
"Looped descriptor" errors.
Reported-by: Hans Middelhoek <h.middelhoek@ospito.nl>
Link: https://forum.proxmox.com/threads/vm-crash-with-memory-hotplug.35904/
Fixes: 3b3b0628217e ("virtio: slim down allocation of VirtQueueElements")
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/virtio/virtio.c')
-rw-r--r-- | hw/virtio/virtio.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 311929e..5884ce3 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -834,7 +834,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) int64_t len; VirtIODevice *vdev = vq->vdev; VirtQueueElement *elem = NULL; - unsigned out_num, in_num; + unsigned out_num, in_num, elem_entries; hwaddr addr[VIRTQUEUE_MAX_SIZE]; struct iovec iov[VIRTQUEUE_MAX_SIZE]; VRingDesc desc; @@ -852,7 +852,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) smp_rmb(); /* When we start there are none of either input nor output. */ - out_num = in_num = 0; + out_num = in_num = elem_entries = 0; max = vq->vring.num; @@ -922,7 +922,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) } /* If we've got too many, that implies a descriptor loop. */ - if ((in_num + out_num) > max) { + if (++elem_entries > max) { virtio_error(vdev, "Looped descriptor"); goto err_undo_map; } |