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 <yangtianyu2@huawei.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454832
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Tianyu yang 2019-05-17 10:19:02 +08:00 committed by Changpeng Liu
parent 4003ebf73c
commit 151a357ca3
4 changed files with 4 additions and 13 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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)