Commit 151a357c authored by Tianyu yang's avatar Tianyu yang Committed by Changpeng Liu
Browse files

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: default avatarTianyu yang <yangtianyu2@huawei.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/454832


Reviewed-by: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 4003ebf7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
	}
+2 −1
Original line number Diff line number Diff line
@@ -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;
}
+1 −1
Original line number Diff line number Diff line
@@ -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);
+0 −10
Original line number Diff line number Diff line
@@ -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)