From 151a357ca37d30b485178ebf7b96504f6bd09f5f Mon Sep 17 00:00:00 2001 From: Tianyu yang Date: Fri, 17 May 2019 10:19:02 +0800 Subject: [PATCH] rte_vhost: fix deadlock on rte_vhost_driver_unregister() when qemu connect to vhost, but don't send msg to vhost. We use kill -15 to destroy vhost process. it will lead to deadlock. (A) * rte_vhost_driver_unregister() * pthread_mutex_lock hold vhost_user.mutex (1) * wait TAILQ_FIRST(&vsocket->conn_list) is NULL (B) * fdset_event_dispatch() * vhost_user_read_cb() start * vhost_user_msg_handler() start * dev->notify_ops is NULL because qemu just connect, no message recv. * vhost_driver_callback_get() * pthread_mutex_lock hold vhost_user.mutex (2) (A) & (B) deadlock To avoid this scenes, when qemu connect in vhost_new_device() initialize dev->notify_ops Change-Id: Iaf699da41dfa3088cfc0f09688b50fada6b2c8d6 Signed-off-by: Tianyu yang Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454832 Reviewed-by: Darek Stojaczyk Reviewed-by: Ben Walker Reviewed-by: Changpeng Liu Tested-by: SPDK CI Jenkins --- lib/vhost/rte_vhost/socket.c | 2 +- lib/vhost/rte_vhost/vhost.c | 3 ++- lib/vhost/rte_vhost/vhost.h | 2 +- lib/vhost/rte_vhost/vhost_user.c | 10 ---------- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/lib/vhost/rte_vhost/socket.c b/lib/vhost/rte_vhost/socket.c index 5d6959c65..1d69e630e 100644 --- a/lib/vhost/rte_vhost/socket.c +++ b/lib/vhost/rte_vhost/socket.c @@ -220,7 +220,7 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket) return; } - vid = vhost_new_device(vsocket->features); + vid = vhost_new_device(vsocket->features, vsocket->notify_ops); if (vid == -1) { goto err; } diff --git a/lib/vhost/rte_vhost/vhost.c b/lib/vhost/rte_vhost/vhost.c index e2db306b4..8e78bf9a0 100644 --- a/lib/vhost/rte_vhost/vhost.c +++ b/lib/vhost/rte_vhost/vhost.c @@ -181,7 +181,7 @@ reset_device(struct virtio_net *dev) * there is a new virtio device being attached). */ int -vhost_new_device(uint64_t features) +vhost_new_device(uint64_t features, struct vhost_device_ops const *ops) { struct virtio_net *dev; int i; @@ -207,6 +207,7 @@ vhost_new_device(uint64_t features) vhost_devices[i] = dev; dev->vid = i; dev->features = features; + dev->notify_ops = ops; return i; } diff --git a/lib/vhost/rte_vhost/vhost.h b/lib/vhost/rte_vhost/vhost.h index db20d9bde..6f9e9a436 100644 --- a/lib/vhost/rte_vhost/vhost.h +++ b/lib/vhost/rte_vhost/vhost.h @@ -301,7 +301,7 @@ gpa_to_hpa(struct virtio_net *dev, uint64_t gpa, uint64_t size) struct virtio_net *get_device(int vid); -int vhost_new_device(uint64_t features); +int vhost_new_device(uint64_t features, struct vhost_device_ops const *ops); void cleanup_device(struct virtio_net *dev, int destroy); void reset_device(struct virtio_net *dev); void vhost_destroy_device(int); diff --git a/lib/vhost/rte_vhost/vhost_user.c b/lib/vhost/rte_vhost/vhost_user.c index e73bab8a5..a07483fcf 100644 --- a/lib/vhost/rte_vhost/vhost_user.c +++ b/lib/vhost/rte_vhost/vhost_user.c @@ -1217,16 +1217,6 @@ vhost_user_msg_handler(int vid, int fd) if (dev == NULL) return -1; - if (!dev->notify_ops) { - dev->notify_ops = vhost_driver_callback_get(dev->ifname); - if (!dev->notify_ops) { - RTE_LOG(ERR, VHOST_CONFIG, - "failed to get callback ops for driver %s\n", - dev->ifname); - return -1; - } - } - ret = read_vhost_message(fd, &msg); if (ret <= 0 || msg.request >= VHOST_USER_MAX) { if (ret < 0)