[CRIU] [PATCH v2 4/9] restore: socket queues support

Kinsbursky Stanislav skinsbursky at openvz.org
Wed Feb 29 08:06:56 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 file have to be readed first and then packets entries
with offset for it's data in image will be 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 use sendfile() top send them to the
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 |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 76 insertions(+), 0 deletions(-)

diff --git a/sockets.c b/sockets.c
index 52bf91e..6c7b99f 100644
--- a/sockets.c
+++ b/sockets.c
@@ -12,6 +12,7 @@
 #include <unistd.h>
 #include <limits.h>
 #include <arpa/inet.h>
+#include <sys/sendfile.h>
 
 #include "types.h"
 #include "libnetlink.h"
@@ -675,6 +676,81 @@ out:
 	return err;
 }
 
+struct sk_packet {
+	struct list_head list;
+	struct sk_packet_entry entry;
+	off_t img_off;
+};
+
+struct sk_packets_pool {
+	struct list_head packets_list;
+	int img_fd;
+};
+
+static int read_sockets_queues(struct sk_packets_pool *pool)
+{
+	struct sk_packet *pkt;
+	int ret;
+
+	pr_info("Trying to read socket queues image\n");
+
+	lseek(pool->img_fd, MAGIC_OFFSET, SEEK_SET);
+	while (1) {
+		struct sk_packet_entry tmp;
+
+		pkt = xmalloc(sizeof(*pkt));
+		if (!pkt) {
+			pr_err("Failed to allocate packet header\n");
+			return -ENOMEM;
+		}
+		ret = read_img_eof(pool->img_fd, &pkt->entry);
+		if (ret <= 0)
+			break;
+		pkt->img_off = lseek(pool->img_fd, 0, SEEK_CUR);
+		/*
+		 * NOTE: packet must be added to the tail. Otherwise sequence
+		 * will be broken.
+		 */
+		list_add_tail(&pkt->list, &pool->packets_list);
+		lseek(pool->img_fd, pkt->entry.length, SEEK_CUR);
+	}
+	xfree(pkt);
+	return ret;
+}
+
+static int restore_socket_queue(struct sk_packets_pool *pool, int fd,
+				unsigned int peer_id)
+{
+	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, &pool->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 = sendfile(fd, pool->img_fd, &pkt->img_off, entry->length);
+		if (ret < 0) {
+			pr_perror("Failed to sendfile packet");
+			return -1;
+		}
+		if (ret != entry->length) {
+			pr_err("Restored skb trimmed to %d/%d\n",
+					ret, entry->length);
+			return -1;
+		}
+		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