Commit 40aa38a651 for qemu.org

commit 40aa38a651a8d4ca99c70e591176a97abcae5295
Author: Stefan Hajnoczi <stefanha@redhat.com>
Date:   Tue Mar 11 21:26:16 2025 +0800

    virtio-scsi: only expose cmd vqs via iothread-vq-mapping

    Peter Krempa and Kevin Wolf observed that iothread-vq-mapping is
    confusing to use because the control and event virtqueues have a fixed
    location before the command virtqueues but need to be treated
    differently.

    Only expose the command virtqueues via iothread-vq-mapping so that the
    command-line parameter is intuitive: it controls where SCSI requests are
    processed.

    The control virtqueue needs to be hardcoded to the main loop thread for
    technical reasons anyway. Kevin also pointed out that it's better to
    place the event virtqueue in the main loop thread since its no poll
    behavior would prevent polling if assigned to an IOThread.

    This change is its own commit to avoid squashing the previous commit.

    Suggested-by: Kevin Wolf <kwolf@redhat.com>
    Suggested-by: Peter Krempa <pkrempa@redhat.com>
    Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
    Message-ID: <20250311132616.1049687-14-stefanha@redhat.com>
    Tested-by: Peter Krempa <pkrempa@redhat.com>
    Signed-off-by: Kevin Wolf <kwolf@redhat.com>

diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
index 2d37fa6712..95f13fb7c2 100644
--- a/hw/scsi/virtio-scsi-dataplane.c
+++ b/hw/scsi/virtio-scsi-dataplane.c
@@ -28,7 +28,6 @@ void virtio_scsi_dataplane_setup(VirtIOSCSI *s, Error **errp)
     VirtIODevice *vdev = VIRTIO_DEVICE(s);
     BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
-    uint16_t num_vqs = vs->conf.num_queues + VIRTIO_SCSI_VQ_NUM_FIXED;

     if (vs->conf.iothread && vs->conf.iothread_vq_mapping_list) {
         error_setg(errp,
@@ -50,35 +49,43 @@ void virtio_scsi_dataplane_setup(VirtIOSCSI *s, Error **errp)
         }
     }

-    s->vq_aio_context = g_new(AioContext *, num_vqs);
+    s->vq_aio_context = g_new(AioContext *, vs->conf.num_queues +
+                                            VIRTIO_SCSI_VQ_NUM_FIXED);
+
+    /*
+     * Handle the ctrl virtqueue in the main loop thread where device resets
+     * can be performed.
+     */
+    s->vq_aio_context[0] = qemu_get_aio_context();
+
+    /*
+     * Handle the event virtqueue in the main loop thread where its no_poll
+     * behavior won't stop IOThread polling.
+     */
+    s->vq_aio_context[1] = qemu_get_aio_context();

     if (vs->conf.iothread_vq_mapping_list) {
         if (!iothread_vq_mapping_apply(vs->conf.iothread_vq_mapping_list,
-                                       s->vq_aio_context, num_vqs, errp)) {
+                    &s->vq_aio_context[VIRTIO_SCSI_VQ_NUM_FIXED],
+                    vs->conf.num_queues, errp)) {
             g_free(s->vq_aio_context);
             s->vq_aio_context = NULL;
             return;
         }
     } else if (vs->conf.iothread) {
         AioContext *ctx = iothread_get_aio_context(vs->conf.iothread);
-        for (uint16_t i = 0; i < num_vqs; i++) {
-            s->vq_aio_context[i] = ctx;
+        for (uint16_t i = 0; i < vs->conf.num_queues; i++) {
+            s->vq_aio_context[VIRTIO_SCSI_VQ_NUM_FIXED + i] = ctx;
         }

         /* Released in virtio_scsi_dataplane_cleanup() */
         object_ref(OBJECT(vs->conf.iothread));
     } else {
         AioContext *ctx = qemu_get_aio_context();
-        for (unsigned i = 0; i < num_vqs; i++) {
-            s->vq_aio_context[i] = ctx;
+        for (unsigned i = 0; i < vs->conf.num_queues; i++) {
+            s->vq_aio_context[VIRTIO_SCSI_VQ_NUM_FIXED + i] = ctx;
         }
     }
-
-    /*
-     * Always handle the ctrl virtqueue in the main loop thread where device
-     * resets can be performed.
-     */
-    s->vq_aio_context[0] = qemu_get_aio_context();
 }

 /* Context: BQL held */