--- /dev/null
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Stefan Hajnoczi <stefanha@redhat.com>
+Date: Mon, 22 Jan 2024 12:26:25 -0500
+Subject: [PATCH] virtio-blk: avoid using ioeventfd state in irqfd conditional
+
+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>
+[FE: backport: dataplane -> ioeventfd rework didn't happen yet]
+Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
+---
+ hw/block/virtio-blk.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
+index 39e7f23fab..61bd1f6859 100644
+--- a/hw/block/virtio-blk.c
++++ b/hw/block/virtio-blk.c
+@@ -64,7 +64,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);