Skip to content

Commit

Permalink
[VIRTIO] Freeze and Restore Implementation.
Browse files Browse the repository at this point in the history
Whenever VM goes for suspend if there are any
active VSOCK connections used to communicate with host,
respective vsock connections were unable to resume as
freeze and restore functionality was not implemented in
virtio driver.

This change will fix VSOCK reconnect in case
of Suspend and Resume

In freeze case:
Change will reset all connected sockets when the device
disappears and flush all device writes and interrupts
and also delete virtqueues and flush outstanding
callbacks if any.

In Restore case:
Change will initialize all the necessary parameter to
make the virtio device ready

Tracked-On: OAM-100107
Signed-off-by: Stefano Garzarella <[email protected]>
Signed-off-by: Vilas R K <[email protected]>
Signed-off-by: Bharat Panda <[email protected]>
  • Loading branch information
vilasrk authored and sysopenci committed Jun 11, 2022
1 parent bd0f16c commit 26b9625
Showing 1 changed file with 152 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
From ac91eeb67b4f235fee19c000aff27b8e1991ad53 Mon Sep 17 00:00:00 2001
From: Vilas R K <[email protected]>
Date: Wed, 23 Mar 2022 21:05:33 +0530
Subject: [PATCH] Freeze and Restore Implementation.

Whenever VM goes for suspend if there are any
active VSOCK connections used to communicate with host
respective vsock connections were unable to resume as
freeze and restore functionality was not implemented i
virtio driver.
This change will fix VSOCK reconnect in case
of Suspend and Resume

In freeze case:
Change will reset all connected sockets when the devic
disappears and flush all device writes and interrupts
and also delete virtqueues and flush outstanding
callbacks if any.

In Restore case:
Change will initialize all the necessary parameter to
make the virtio device ready

Tracked-On: OAM-100107
Signed-off-by: Stefano Garzarella <[email protected]
Signed-off-by: Vilas R K <[email protected]>
Signed-off-by: Bharat Panda <[email protected]>
---
net/vmw_vsock/virtio_transport.c | 100 +++++++++++++++++++++++++++++++
1 file changed, 100 insertions(+)

diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
index 9d012817cefc..f505f476973d 100644
--- a/net/vmw_vsock/virtio_transport.c
+++ b/net/vmw_vsock/virtio_transport.c
@@ -696,6 +696,104 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
kfree(vsock);
}

+static int virtio_vsock_freeze(struct virtio_device *vdev)
+{
+ struct virtio_vsock *vsock = vdev->priv;
+ struct virtio_vsock_pkt *pkt;
+ mutex_lock(&the_virtio_vsock_mutex);
+ rcu_assign_pointer(the_virtio_vsock, NULL);
+ synchronize_rcu();
+ /* Reset all connected sockets when the device disappear */
+ // vsock_for_each_connected_socket(&virtio_transport.transport,virtio_vsock_reset_sock); //Original
+ vsock_for_each_connected_socket(virtio_vsock_reset_sock);
+ /* Stop all work handlers to make sure no one is accessing the device,
+ * so we can safely call virtio_reset_device().
+ */
+ mutex_lock(&vsock->rx_lock);
+ vsock->rx_run = false;
+ mutex_unlock(&vsock->rx_lock);
+ mutex_lock(&vsock->tx_lock);
+ vsock->tx_run = false;
+ mutex_unlock(&vsock->tx_lock);
+ mutex_lock(&vsock->event_lock);
+ vsock->event_run = false;
+ mutex_unlock(&vsock->event_lock);
+
+ mutex_lock(&vsock->rx_lock);
+ while ((pkt = virtqueue_detach_unused_buf(vsock->vqs[VSOCK_VQ_RX])))
+ virtio_transport_free_pkt(pkt);
+ mutex_unlock(&vsock->rx_lock);
+ mutex_lock(&vsock->tx_lock);
+ while ((pkt = virtqueue_detach_unused_buf(vsock->vqs[VSOCK_VQ_TX])))
+ virtio_transport_free_pkt(pkt);
+ mutex_unlock(&vsock->tx_lock);
+ spin_lock_bh(&vsock->send_pkt_list_lock);
+ while (!list_empty(&vsock->send_pkt_list)) {
+ pkt = list_first_entry(&vsock->send_pkt_list,
+ struct virtio_vsock_pkt, list);
+ list_del(&pkt->list);
+ virtio_transport_free_pkt(pkt);
+ }
+ spin_unlock_bh(&vsock->send_pkt_list_lock);
+ /* Delete virtqueues and flush outstanding callbacks if any */
+ vdev->config->del_vqs(vdev);
+
+ /* Other works can be queued before 'config->del_vqs()', so we flush
+ * all works before to free the vsock object to avoid use after free.
+ */
+ flush_work(&vsock->rx_work);
+ flush_work(&vsock->tx_work);
+ flush_work(&vsock->event_work);
+ flush_work(&vsock->send_pkt_work);
+
+ mutex_unlock(&the_virtio_vsock_mutex);
+
+ printk("virtio_vsock_freeze: ok\n");
+
+ return 0;
+}
+
+static int virtio_vsock_restore(struct virtio_device *vdev)
+{
+ vq_callback_t *callbacks[] = {
+ virtio_vsock_rx_done,
+ virtio_vsock_tx_done,
+ virtio_vsock_event_done,
+ };
+ static const char * const names[] = {
+ "rx",
+ "tx",
+ "event",
+ };
+ struct virtio_vsock *vsock = vdev->priv;
+ int ret;
+ mutex_lock(&the_virtio_vsock_mutex);
+ ret = virtio_find_vqs(vsock->vdev, VSOCK_VQ_MAX,
+ vsock->vqs, callbacks, names,
+ NULL);
+ if (ret < 0)
+ goto out;
+ virtio_device_ready(vdev);
+ virtio_vsock_update_guest_cid(vsock);
+ vsock_for_each_connected_socket(virtio_vsock_reset_sock);
+ mutex_lock(&vsock->tx_lock);
+ vsock->tx_run = true;
+ mutex_unlock(&vsock->tx_lock);
+ mutex_lock(&vsock->rx_lock);
+ virtio_vsock_rx_fill(vsock);
+ vsock->rx_run = true;
+ mutex_unlock(&vsock->rx_lock);
+ mutex_lock(&vsock->event_lock);
+ virtio_vsock_event_fill(vsock);
+ vsock->event_run = true;
+ mutex_unlock(&vsock->event_lock);
+ rcu_assign_pointer(the_virtio_vsock, vsock);
+ printk("virtio_vsock_restore: ok\n");
+ ret = 0;
+out:
+ mutex_unlock(&the_virtio_vsock_mutex);
+ return ret;
+}
static struct virtio_device_id id_table[] = {
{ VIRTIO_ID_VSOCK, VIRTIO_DEV_ANY_ID },
{ 0 },
@@ -712,6 +810,8 @@ static struct virtio_driver virtio_vsock_driver = {
.id_table = id_table,
.probe = virtio_vsock_probe,
.remove = virtio_vsock_remove,
+ .freeze = virtio_vsock_freeze,
+ .restore = virtio_vsock_restore,
};

static int __init virtio_vsock_init(void)
--
2.17.1

0 comments on commit 26b9625

Please sign in to comment.