]> git.droids-corp.org - dpdk.git/commitdiff
net/virtio-user: fix socket non-blocking mode
authorYuan Wang <yuanx.wang@intel.com>
Fri, 17 Jun 2022 02:42:29 +0000 (10:42 +0800)
committerMaxime Coquelin <maxime.coquelin@redhat.com>
Fri, 1 Jul 2022 13:49:32 +0000 (15:49 +0200)
The virtio-user initialization requires unix socket to receive backend
messages in block mode. However, vhost_user_update_link_state() sets
the same socket to nonblocking via fcntl, which affects all threads.
Enabling the rxq interrupt can causes both of these behaviors to occur
concurrently, with the result that the initialization may fail
because no messages are received in nonblocking socket.

Thread 1:
virtio_init_device()
--> virtio_user_start_device()
--> vhost_user_set_memory_table()
--> vhost_user_check_reply_ack()

Thread 2:
virtio_interrupt_handler()
--> vhost_user_update_link_state()

Fix that by replacing O_NONBLOCK with the recv per-call option
MSG_DONTWAIT.

Fixes: ef53b6030039 ("net/virtio-user: support LSC")
Cc: stable@dpdk.org
Signed-off-by: Yuan Wang <yuanx.wang@intel.com>
Acked-by: Stephen Hemminger <stephen@networkplumber.org>
Reviewed-by: Chenbo Xia <chenbo.xia@intel.com>
drivers/net/virtio/virtio_user/vhost_user.c

index 7d1749114d4f1c0f136fd3da68627df1da6f0f6c..198bd63d3c37d74681e526afe7017e85c401ef42 100644 (file)
@@ -940,15 +940,8 @@ vhost_user_update_link_state(struct virtio_user_dev *dev)
 
        if (data->vhostfd >= 0) {
                int r;
-               int flags;
 
-               flags = fcntl(data->vhostfd, F_GETFL);
-               if (fcntl(data->vhostfd, F_SETFL, flags | O_NONBLOCK) == -1) {
-                       PMD_DRV_LOG(ERR, "error setting O_NONBLOCK flag");
-                       return -1;
-               }
-
-               r = recv(data->vhostfd, buf, 128, MSG_PEEK);
+               r = recv(data->vhostfd, buf, 128, MSG_PEEK | MSG_DONTWAIT);
                if (r == 0 || (r < 0 && errno != EAGAIN)) {
                        dev->net_status &= (~VIRTIO_NET_S_LINK_UP);
                        PMD_DRV_LOG(ERR, "virtio-user port %u is down", dev->hw.port_id);
@@ -963,12 +956,6 @@ vhost_user_update_link_state(struct virtio_user_dev *dev)
                } else {
                        dev->net_status |= VIRTIO_NET_S_LINK_UP;
                }
-
-               if (fcntl(data->vhostfd, F_SETFL,
-                                       flags & ~O_NONBLOCK) == -1) {
-                       PMD_DRV_LOG(ERR, "error clearing O_NONBLOCK flag");
-                       return -1;
-               }
        } else if (dev->is_server) {
                dev->net_status &= (~VIRTIO_NET_S_LINK_UP);
                if (virtio_user_dev_server_reconnect(dev) >= 0)