79c4324644
Change-Id: I2d302dda68298877c65c99147f5bf22186a59aac
52 lines
2.0 KiB
Diff
52 lines
2.0 KiB
Diff
From 671f0830d70c1e35deb63cc66db7ce8b713e8967 Mon Sep 17 00:00:00 2001
|
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
Date: Tue, 30 Nov 2021 13:45:10 +0000
|
|
Subject: [PATCH] virtio: signal after wrapping packed used_idx
|
|
|
|
Packed Virtqueues wrap used_idx instead of letting it run freely like
|
|
Split Virtqueues do. If the used ring wraps more than once there is no
|
|
way to compare vq->signalled_used and vq->used_idx in
|
|
virtio_packed_should_notify() since they are modulo vq->vring.num.
|
|
|
|
This causes the device to stop sending used buffer notifications when
|
|
when virtio_packed_should_notify() is called less than once each time
|
|
around the used ring.
|
|
|
|
It is possible to trigger this with virtio-blk's dataplane
|
|
notify_guest_bh() irq coalescing optimization. The call to
|
|
virtio_notify_irqfd() (and virtio_packed_should_notify()) is deferred to
|
|
a BH. If the guest driver is polling it can complete and submit more
|
|
requests before the BH executes, causing the used ring to wrap more than
|
|
once. The result is that the virtio-blk device ceases to raise
|
|
interrupts and I/O hangs.
|
|
|
|
Cc: Tiwei Bie <tiwei.bie@intel.com>
|
|
Cc: Jason Wang <jasowang@redhat.com>
|
|
Cc: Michael S. Tsirkin <mst@redhat.com>
|
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
Message-Id: <20211130134510.267382-1-stefanha@redhat.com>
|
|
Fixes: 86044b24e865fb9596ed77a4d0f3af8b90a088a1 ("virtio: basic packed virtqueue support")
|
|
Acked-by: Jason Wang <jasowang@redhat.com>
|
|
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
|
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
|
Signed-off-by: fangyi <eric.fangyi@huawei.com>
|
|
---
|
|
hw/virtio/virtio.c | 1 +
|
|
1 file changed, 1 insertion(+)
|
|
|
|
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
|
|
index d90cabe868..05409b84d1 100644
|
|
--- a/hw/virtio/virtio.c
|
|
+++ b/hw/virtio/virtio.c
|
|
@@ -885,6 +885,7 @@ static void virtqueue_packed_flush(VirtQueue *vq, unsigned int count)
|
|
if (vq->used_idx >= vq->vring.num) {
|
|
vq->used_idx -= vq->vring.num;
|
|
vq->used_wrap_counter ^= 1;
|
|
+ vq->signalled_used_valid = false;
|
|
}
|
|
}
|
|
|
|
--
|
|
2.27.0
|
|
|