7f1c5b
From 9fb47ad317ad8cdda9960190d499ad6c3a9817f0 Mon Sep 17 00:00:00 2001
7f1c5b
From: Greg Kurz <groug@kaod.org>
7f1c5b
Date: Thu, 19 Jan 2023 18:24:23 +0100
7f1c5b
Subject: [PATCH 18/20] Revert "vhost-user: Monitor slave channel in
7f1c5b
 vhost_user_read()"
7f1c5b
MIME-Version: 1.0
7f1c5b
Content-Type: text/plain; charset=UTF-8
7f1c5b
Content-Transfer-Encoding: 8bit
7f1c5b
7f1c5b
RH-Author: Laurent Vivier <lvivier@redhat.com>
7f1c5b
RH-MergeRequest: 146: Fix vhost-user with dpdk
7f1c5b
RH-Bugzilla: 2155173
7f1c5b
RH-Acked-by: Cindy Lu <lulu@redhat.com>
7f1c5b
RH-Acked-by: Greg Kurz (RH) <gkurz@redhat.com>
7f1c5b
RH-Acked-by: Eugenio PĂ©rez <eperezma@redhat.com>
7f1c5b
RH-Commit: [1/2] c583a7f121ca9c93c9a2ad17bf0ccf5c1241dc99 (lvivier/qemu-kvm-centos)
7f1c5b
7f1c5b
This reverts commit db8a3772e300c1a656331a92da0785d81667dc81.
7f1c5b
7f1c5b
Motivation : this is breaking vhost-user with DPDK as reported in [0].
7f1c5b
7f1c5b
Received unexpected msg type. Expected 22 received 40
7f1c5b
Fail to update device iotlb
7f1c5b
Received unexpected msg type. Expected 40 received 22
7f1c5b
Received unexpected msg type. Expected 22 received 11
7f1c5b
Fail to update device iotlb
7f1c5b
Received unexpected msg type. Expected 11 received 22
7f1c5b
vhost VQ 1 ring restore failed: -71: Protocol error (71)
7f1c5b
Received unexpected msg type. Expected 22 received 11
7f1c5b
Fail to update device iotlb
7f1c5b
Received unexpected msg type. Expected 11 received 22
7f1c5b
vhost VQ 0 ring restore failed: -71: Protocol error (71)
7f1c5b
unable to start vhost net: 71: falling back on userspace virtio
7f1c5b
7f1c5b
The failing sequence that leads to the first error is :
7f1c5b
- QEMU sends a VHOST_USER_GET_STATUS (40) request to DPDK on the master
7f1c5b
  socket
7f1c5b
- QEMU starts a nested event loop in order to wait for the
7f1c5b
  VHOST_USER_GET_STATUS response and to be able to process messages from
7f1c5b
  the slave channel
7f1c5b
- DPDK sends a couple of legitimate IOTLB miss messages on the slave
7f1c5b
  channel
7f1c5b
- QEMU processes each IOTLB request and sends VHOST_USER_IOTLB_MSG (22)
7f1c5b
  updates on the master socket
7f1c5b
- QEMU assumes to receive a response for the latest VHOST_USER_IOTLB_MSG
7f1c5b
  but it gets the response for the VHOST_USER_GET_STATUS instead
7f1c5b
7f1c5b
The subsequent errors have the same root cause : the nested event loop
7f1c5b
breaks the order by design. It lures QEMU to expect responses to the
7f1c5b
latest message sent on the master socket to arrive first.
7f1c5b
7f1c5b
Since this was only needed for DAX enablement which is still not merged
7f1c5b
upstream, just drop the code for now. A working solution will have to
7f1c5b
be merged later on. Likely protect the master socket with a mutex
7f1c5b
and service the slave channel with a separate thread, as discussed with
7f1c5b
Maxime in the mail thread below.
7f1c5b
7f1c5b
[0] https://lore.kernel.org/qemu-devel/43145ede-89dc-280e-b953-6a2b436de395@redhat.com/
7f1c5b
7f1c5b
Reported-by: Yanghang Liu <yanghliu@redhat.com>
7f1c5b
Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2155173
7f1c5b
Signed-off-by: Greg Kurz <groug@kaod.org>
7f1c5b
Message-Id: <20230119172424.478268-2-groug@kaod.org>
7f1c5b
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
7f1c5b
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
7f1c5b
Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
7f1c5b
Acked-by: Maxime Coquelin <maxime.coquelin@redhat.com>
7f1c5b
(cherry picked from commit f340a59d5a852d75ae34555723694c7e8eafbd0c)
7f1c5b
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
7f1c5b
---
7f1c5b
 hw/virtio/vhost-user.c | 35 +++--------------------------------
7f1c5b
 1 file changed, 3 insertions(+), 32 deletions(-)
7f1c5b
7f1c5b
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
7f1c5b
index 8f635844af..0ac00eb901 100644
7f1c5b
--- a/hw/virtio/vhost-user.c
7f1c5b
+++ b/hw/virtio/vhost-user.c
7f1c5b
@@ -356,35 +356,6 @@ end:
7f1c5b
     return G_SOURCE_REMOVE;
7f1c5b
 }
7f1c5b
 
7f1c5b
-static gboolean slave_read(QIOChannel *ioc, GIOCondition condition,
7f1c5b
-                           gpointer opaque);
7f1c5b
-
7f1c5b
-/*
7f1c5b
- * This updates the read handler to use a new event loop context.
7f1c5b
- * Event sources are removed from the previous context : this ensures
7f1c5b
- * that events detected in the previous context are purged. They will
7f1c5b
- * be re-detected and processed in the new context.
7f1c5b
- */
7f1c5b
-static void slave_update_read_handler(struct vhost_dev *dev,
7f1c5b
-                                      GMainContext *ctxt)
7f1c5b
-{
7f1c5b
-    struct vhost_user *u = dev->opaque;
7f1c5b
-
7f1c5b
-    if (!u->slave_ioc) {
7f1c5b
-        return;
7f1c5b
-    }
7f1c5b
-
7f1c5b
-    if (u->slave_src) {
7f1c5b
-        g_source_destroy(u->slave_src);
7f1c5b
-        g_source_unref(u->slave_src);
7f1c5b
-    }
7f1c5b
-
7f1c5b
-    u->slave_src = qio_channel_add_watch_source(u->slave_ioc,
7f1c5b
-                                                G_IO_IN | G_IO_HUP,
7f1c5b
-                                                slave_read, dev, NULL,
7f1c5b
-                                                ctxt);
7f1c5b
-}
7f1c5b
-
7f1c5b
 static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
7f1c5b
 {
7f1c5b
     struct vhost_user *u = dev->opaque;
7f1c5b
@@ -406,7 +377,6 @@ static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
7f1c5b
      * be prepared for re-entrancy. So we create a new one and switch chr
7f1c5b
      * to use it.
7f1c5b
      */
7f1c5b
-    slave_update_read_handler(dev, ctxt);
7f1c5b
     qemu_chr_be_update_read_handlers(chr->chr, ctxt);
7f1c5b
     qemu_chr_fe_add_watch(chr, G_IO_IN | G_IO_HUP, vhost_user_read_cb, &data);
7f1c5b
 
7f1c5b
@@ -418,7 +388,6 @@ static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
7f1c5b
      * context that have been processed by the nested loop are purged.
7f1c5b
      */
7f1c5b
     qemu_chr_be_update_read_handlers(chr->chr, prev_ctxt);
7f1c5b
-    slave_update_read_handler(dev, NULL);
7f1c5b
 
7f1c5b
     g_main_loop_unref(loop);
7f1c5b
     g_main_context_unref(ctxt);
7f1c5b
@@ -1802,7 +1771,9 @@ static int vhost_setup_slave_channel(struct vhost_dev *dev)
7f1c5b
         return -ECONNREFUSED;
7f1c5b
     }
7f1c5b
     u->slave_ioc = ioc;
7f1c5b
-    slave_update_read_handler(dev, NULL);
7f1c5b
+    u->slave_src = qio_channel_add_watch_source(u->slave_ioc,
7f1c5b
+                                                G_IO_IN | G_IO_HUP,
7f1c5b
+                                                slave_read, dev, NULL, NULL);
7f1c5b
 
7f1c5b
     if (reply_supported) {
7f1c5b
         msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK;
7f1c5b
-- 
7f1c5b
2.31.1
7f1c5b