]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
virtio-blk: avoid using ioeventfd state in irqfd conditional
authorStefan Hajnoczi <stefanha@redhat.com>
Mon, 22 Jan 2024 17:26:25 +0000 (12:26 -0500)
committerMichael Tokarev <mjt@tls.msk.ru>
Mon, 12 Feb 2024 16:26:03 +0000 (19:26 +0300)
Requests that complete in an IOThread use irqfd to notify the guest
while requests that complete in the main loop thread use the traditional
qdev irq code path. The reason for this conditional is that the irq code
path requires the BQL:

  if (s->ioeventfd_started && !s->ioeventfd_disabled) {
      virtio_notify_irqfd(vdev, req->vq);
  } else {
      virtio_notify(vdev, req->vq);
  }

There is a corner case where the conditional invokes the irq code path
instead of the irqfd code path:

  static void virtio_blk_stop_ioeventfd(VirtIODevice *vdev)
  {
      ...
      /*
       * Set ->ioeventfd_started to false before draining so that host notifiers
       * are not detached/attached anymore.
       */
      s->ioeventfd_started = false;

      /* Wait for virtio_blk_dma_restart_bh() and in flight I/O to complete */
      blk_drain(s->conf.conf.blk);

During blk_drain() the conditional produces the wrong result because
ioeventfd_started is false.

Use qemu_in_iothread() instead of checking the ioeventfd state.

Cc: qemu-stable@nongnu.org
Buglink: https://issues.redhat.com/browse/RHEL-15394
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-ID: <20240122172625.415386-1-stefanha@redhat.com>
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit bfa36802d1704fc413c590ebdcc4e5ae0eacf439)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(Mjt: fixup for v8.2.0-809-g3cdaf3dd4a
 "virtio-blk: rename dataplane to ioeventfd")

hw/block/virtio-blk.c

index a1f8e155227591fb428f065d11658f133e348a6b..31aac145810661aafd1d3c3f531dc418a312c489 100644 (file)
@@ -65,7 +65,7 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, unsigned char status)
     iov_discard_undo(&req->inhdr_undo);
     iov_discard_undo(&req->outhdr_undo);
     virtqueue_push(req->vq, &req->elem, req->in_len);
-    if (s->dataplane_started && !s->dataplane_disabled) {
+    if (qemu_in_iothread()) {
         virtio_blk_data_plane_notify(s->dataplane, req->vq);
     } else {
         virtio_notify(vdev, req->vq);