Commit 22b5c0b6 authored by Stefano Garzarella's avatar Stefano Garzarella Committed by David S. Miller

vsock/virtio: fix kernel panic after device hot-unplug

virtio_vsock_remove() invokes the vsock_core_exit() also if there
are opened sockets for the AF_VSOCK protocol family. In this way
the vsock "transport" pointer is set to NULL, triggering the
kernel panic at the first socket activity.

This patch move the vsock_core_init()/vsock_core_exit() in the
virtio_vsock respectively in module_init and module_exit functions,
that cannot be invoked until there are open sockets.

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1609699Reported-by: default avatarYan Fu <yafu@redhat.com>
Signed-off-by: default avatarStefano Garzarella <sgarzare@redhat.com>
Acked-by: default avatarStefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c14f07c6
...@@ -75,6 +75,9 @@ static u32 virtio_transport_get_local_cid(void) ...@@ -75,6 +75,9 @@ static u32 virtio_transport_get_local_cid(void)
{ {
struct virtio_vsock *vsock = virtio_vsock_get(); struct virtio_vsock *vsock = virtio_vsock_get();
if (!vsock)
return VMADDR_CID_ANY;
return vsock->guest_cid; return vsock->guest_cid;
} }
...@@ -584,10 +587,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev) ...@@ -584,10 +587,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
virtio_vsock_update_guest_cid(vsock); virtio_vsock_update_guest_cid(vsock);
ret = vsock_core_init(&virtio_transport.transport);
if (ret < 0)
goto out_vqs;
vsock->rx_buf_nr = 0; vsock->rx_buf_nr = 0;
vsock->rx_buf_max_nr = 0; vsock->rx_buf_max_nr = 0;
atomic_set(&vsock->queued_replies, 0); atomic_set(&vsock->queued_replies, 0);
...@@ -618,8 +617,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev) ...@@ -618,8 +617,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
mutex_unlock(&the_virtio_vsock_mutex); mutex_unlock(&the_virtio_vsock_mutex);
return 0; return 0;
out_vqs:
vsock->vdev->config->del_vqs(vsock->vdev);
out: out:
kfree(vsock); kfree(vsock);
mutex_unlock(&the_virtio_vsock_mutex); mutex_unlock(&the_virtio_vsock_mutex);
...@@ -669,7 +666,6 @@ static void virtio_vsock_remove(struct virtio_device *vdev) ...@@ -669,7 +666,6 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
mutex_lock(&the_virtio_vsock_mutex); mutex_lock(&the_virtio_vsock_mutex);
the_virtio_vsock = NULL; the_virtio_vsock = NULL;
vsock_core_exit();
mutex_unlock(&the_virtio_vsock_mutex); mutex_unlock(&the_virtio_vsock_mutex);
vdev->config->del_vqs(vdev); vdev->config->del_vqs(vdev);
...@@ -702,14 +698,28 @@ static int __init virtio_vsock_init(void) ...@@ -702,14 +698,28 @@ static int __init virtio_vsock_init(void)
virtio_vsock_workqueue = alloc_workqueue("virtio_vsock", 0, 0); virtio_vsock_workqueue = alloc_workqueue("virtio_vsock", 0, 0);
if (!virtio_vsock_workqueue) if (!virtio_vsock_workqueue)
return -ENOMEM; return -ENOMEM;
ret = register_virtio_driver(&virtio_vsock_driver); ret = register_virtio_driver(&virtio_vsock_driver);
if (ret) if (ret)
destroy_workqueue(virtio_vsock_workqueue); goto out_wq;
ret = vsock_core_init(&virtio_transport.transport);
if (ret)
goto out_vdr;
return 0;
out_vdr:
unregister_virtio_driver(&virtio_vsock_driver);
out_wq:
destroy_workqueue(virtio_vsock_workqueue);
return ret; return ret;
} }
static void __exit virtio_vsock_exit(void) static void __exit virtio_vsock_exit(void)
{ {
vsock_core_exit();
unregister_virtio_driver(&virtio_vsock_driver); unregister_virtio_driver(&virtio_vsock_driver);
destroy_workqueue(virtio_vsock_workqueue); destroy_workqueue(virtio_vsock_workqueue);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment