[CRIU] [PATCH 4/8] restore: socket queues support

Kinsbursky Stanislav skinsbursky at openvz.org
Tue Feb 28 05:31:33 EST 2012


This patch was designed to be generic and thus usable for all kinds of
sockets. Not sure, thah this goal has been reached, but at least I tried.
Key ideas:
1) sockets queue dump have to be first readed and collected in doubly linked
list by read_sockets_queue() function.
Note: list will contain sockets queues for all (!) the sockets of the task.
2) socket queue can be restored by restore_socket_queue(), which selects
packets from the list by passed id and send them to passed socket. It' also
removes packet from the list and frees it.

Based on xemul@ patches.

Signed-off-by: Stanislav Kinsbursky <skinsbursky at openvz.org>

---
 sockets.c |   78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 78 insertions(+), 0 deletions(-)

diff --git a/sockets.c b/sockets.c
index 52bf91e..e02db03 100644
--- a/sockets.c
+++ b/sockets.c
@@ -675,6 +675,84 @@ out:
 	return err;
 }
 
+struct sk_packet {
+	struct list_head list;
+	struct sk_packet_entry entry;
+};
+
+static int read_sockets_queues(int fd, struct list_head *packets_list)
+{
+	struct sk_packet *pkt;
+	int ret;
+
+	pr_info("Trying to read socket queue\n");
+
+	lseek(fd, MAGIC_OFFSET, SEEK_SET);
+	while (1) {
+		struct sk_packet_entry tmp;
+		struct sk_packet_entry *entry;
+
+		ret = read_img_eof(fd, &tmp);
+		if (ret <= 0)
+			goto out;
+
+		pkt = xmalloc(sizeof(*pkt) + tmp.length);
+		if (!pkt) {
+			pr_info("Failed to allocate packet header\n");
+			return -ENOMEM;
+		}
+		entry = &pkt->entry;
+		memcpy(entry, &tmp, sizeof(tmp));
+
+		ret = read_img_buf(fd, entry->data, entry->length);
+		if (ret < 0)
+			break;
+		/*
+		 * NOTE: packet must be added to the tail. Otherwise sequence
+		 * will be broken.
+		 */
+		list_add_tail(&pkt->list, packets_list);
+	}
+	xfree(pkt);
+out:
+	return ret;
+
+}
+
+static int restore_socket_queue(int fd, unsigned int peer_id,
+				struct list_head *packets_list)
+{
+	struct sk_packet *pkt, *tmp;
+	int ret;
+
+	pr_info("Trying to restore recv queue for %u\n", peer_id);
+
+	list_for_each_entry_safe(pkt, tmp, packets_list, list) {
+		struct sk_packet_entry *entry = &pkt->entry;
+
+		if (entry->id_for != peer_id)
+			continue;
+
+		pr_info("\tRestoring %d-bytes skb for %u\n",
+				entry->length, peer_id);
+
+		ret = send(fd, entry->data, entry->length, MSG_DONTWAIT);
+		if (ret < 0) {
+			pr_perror("Failed to restore skb");
+			return -1;
+		}
+		if (ret != entry->length) {
+			pr_err("Restored skb trimmed to %d/%d\n",
+					ret, entry->length);
+			ret = -1;
+			break;
+		}
+		list_del(&pkt->list);
+		xfree(pkt);
+	}
+	return 0;
+}
+
 static void prep_conn_addr(int id, struct sockaddr_un *addr, int *addrlen)
 {
 	addr->sun_family = AF_UNIX;



More information about the CRIU mailing list