[CRIU] [crtools-bot for Kinsbursky Stanislav ] restore: socket queues support

Cyrill Gorcunov gorcunov at openvz.org
Wed Feb 29 08:42:30 EST 2012


The commit is pushed to "master" and will appear on git://github.com/cyrillos/crtools.git
------>
commit e6f39a41bf6ccfea766114884cc65c7f5d25f21c
Author: Kinsbursky Stanislav <skinsbursky at openvz.org>
Date:   Wed Feb 29 16:06:56 2012 +0300

    restore: socket queues support
    
    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>
    Acked-by: Pavel Emelyanov <xemul at parallels.com>
    Signed-off-by: Cyrill Gorcunov <gorcunov 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