Re: [PATCH kvmtool] virtio: 9p: Order used ring updates before notifications
Will Deacon <[email protected]>
| Newsgroups | org.kernel.vger.kvm |
|---|---|
| Message-ID | <[email protected]> |
On Fri, Jul 24, 2026 at 05:10:41PM +0800, Xie Bo wrote:
> virtio_p9_do_io() signals the guest immediately after adding each
> request to the used ring. Unlike the block and net backends, it bypasses
> virtio_queue__should_signal(), which provides the full memory barrier
> needed between publishing used->idx and injecting the interrupt.
>
> On weakly ordered architectures, the guest can therefore handle the
> interrupt before the updated used->idx becomes visible. If it observes
> the old index and goes back to sleep, the completed request can remain
> stuck indefinitely because no further interrupt is generated.
>
> This was observed on RISC-V with two 9p RPCs blocked while the host
> used->idx was two entries ahead of the guest's last_used_idx.
>
> Process all available requests first, then use
> virtio_queue__should_signal() before notifying the guest. Besides
> providing the required ordering, this also honors the driver's
> notification suppression request.
>
> Fixes: 1c7850f95903 ("kvm tools: Add virtio-9p")
> Signed-off-by: Xie Bo <[email protected]>
> ---
> virtio/9p.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/virtio/9p.c b/virtio/9p.c
> index cf3e547..d2680e9 100644
> --- a/virtio/9p.c
> +++ b/virtio/9p.c
> @@ -1372,11 +1372,15 @@ static void virtio_p9_do_io(struct kvm *kvm, void *param)
> struct p9_dev_job *job = (struct p9_dev_job *)param;
> struct p9_dev *p9dev = job->p9dev;
> struct virt_queue *vq = job->vq;
> + bool completed = false;
>
> while (virt_queue__available(vq)) {
> virtio_p9_do_io_request(kvm, job);
> - p9dev->vdev.ops->signal_vq(kvm, &p9dev->vdev, vq - p9dev->vqs);
> + completed = true;
> }
> +
> + if (completed && virtio_queue__should_signal(vq))
> + p9dev->vdev.ops->signal_vq(kvm, &p9dev->vdev, vq - p9dev->vqs);
Why do you need the 'completed' bool here? Can't we just rely on
virtio_queue__should_signal() instead?
Will