aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2016-11-16 20:17:32 +0000
committerMichael S. Tsirkin <mst@redhat.com>2016-11-18 17:14:10 +0200
commit600f5ce356b44d8fa5a611ff6b034eb95ecf04e7 (patch)
tree194fa4413e7dded3bc187ff5a9e1ae7e31822182 /hw
parent453ac8835b002263a6b7b0843e7c90fa8b19c869 (diff)
downloadqemu-600f5ce356b44d8fa5a611ff6b034eb95ecf04e7.zip
qemu-600f5ce356b44d8fa5a611ff6b034eb95ecf04e7.tar.gz
qemu-600f5ce356b44d8fa5a611ff6b034eb95ecf04e7.tar.bz2
virtio-crypto: fix virtio_queue_set_notification() race
We must check for new virtqueue buffers after re-enabling notifications. This prevents the race condition where the guest added buffers just after we stopped popping the virtqueue but before we re-enabled notifications. I think the virtio-crypto code was based on virtio-net but this crucial detail was missed. virtio-net does not have the race condition because it processes the virtqueue one more time after re-enabling notifications. Cc: Gonglei <arei.gonglei@huawei.com> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Gonglei <arei.gonglei@huawei.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/virtio/virtio-crypto.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index 3293843..847dc9d 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -692,8 +692,17 @@ static void virtio_crypto_dataq_bh(void *opaque)
return;
}
- virtio_crypto_handle_dataq(vdev, q->dataq);
- virtio_queue_set_notification(q->dataq, 1);
+ for (;;) {
+ virtio_crypto_handle_dataq(vdev, q->dataq);
+ virtio_queue_set_notification(q->dataq, 1);
+
+ /* Are we done or did the guest add more buffers? */
+ if (virtio_queue_empty(q->dataq)) {
+ break;
+ }
+
+ virtio_queue_set_notification(q->dataq, 0);
+ }
}
static void