[CRIU] [PATCH v4 13/15] sk-queue: Allow to use several file descriptors to restore a queue

Kirill Tkhai ktkhai at virtuozzo.com
Wed Jun 1 09:03:30 PDT 2016


Since promiscous queues have several senders, we should allow them
to choose, which file descriptor to use to restore a packet.

Also, now we use sendto(), instead of write(), to restore a packet,
since a receiver may be not our peer.

Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
 criu/include/sk-queue.h |   19 ++++++++++++++++++-
 criu/sk-queue.c         |   37 ++++++++++++++++++++++++++++++++-----
 2 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/criu/include/sk-queue.h b/criu/include/sk-queue.h
index 0ad9da2..3ab28d5 100644
--- a/criu/include/sk-queue.h
+++ b/criu/include/sk-queue.h
@@ -1,6 +1,8 @@
 #ifndef __CR_SK_QUEUE_H__
 #define __CR_SK_QUEUE_H__
 
+#include "./images/sk-packet.pb-c.h"
+
 #define SK_NONAME_SENDER	(~0ULL)
 
 struct sk_ino {
@@ -8,9 +10,24 @@ struct sk_ino {
 	u32 ino;
 };
 
+struct sk_fd {
+	struct sockaddr *addr;
+	socklen_t addrlen;
+	int fd;
+};
+
 extern struct collect_image_info sk_queues_cinfo;
 extern int dump_sk_queue(int sock_fd, int sock_id, u64 (*get_sender)(const char *, int));
-extern int restore_sk_queue(int fd, unsigned int peer_id);
+extern int __restore_sk_queue(struct sk_fd **sks, int (*get_fd)(struct sk_fd **, SkPacketEntry *),
+			      unsigned int peer_id, struct sockaddr *dst_addr, socklen_t dst_len);
+static inline int restore_sk_queue(int fd, unsigned int peer_id)
+{
+	struct sk_fd sk = { .fd = fd };
+	struct sk_fd *sks[2] = { &sk, NULL };
+
+	return __restore_sk_queue(sks, NULL, peer_id, NULL, 0);
+}
+
 extern int resolve_senders(unsigned int id, u32 ino, int (*add_receiver)(u32, struct sk_ino *, bool, void *), void *);
 
 #endif /* __CR_SK_QUEUE_H__ */
diff --git a/criu/sk-queue.c b/criu/sk-queue.c
index f40bc2d..bee6fb5 100644
--- a/criu/sk-queue.c
+++ b/criu/sk-queue.c
@@ -267,16 +267,26 @@ int resolve_senders(unsigned int id, u32 ino, int (*add_receiver)(u32, struct sk
 	return -1;
 }
 
-int restore_sk_queue(int fd, unsigned int peer_id)
+static int get_first_fd(struct sk_fd **sks, SkPacketEntry *pkt)
+{
+	return sks[0]->fd;
+}
+
+int __restore_sk_queue(struct sk_fd **sks, int (*get_fd)(struct sk_fd**, SkPacketEntry *),
+		       unsigned int peer_id, struct sockaddr *dst_addr, socklen_t dst_addrlen)
 {
 	struct sk_packet *pkt, *tmp;
-	int ret;
+	int i, fd, noname_fd = -1, ret;
 	struct cr_img *img;
 
 	pr_info("Trying to restore recv queue for %u\n", peer_id);
 
-	if (restore_prepare_socket(fd))
-		return -1;
+	for (i = 0; sks[i]; i++)
+		if (restore_prepare_socket(sks[i]->fd))
+			return -1;
+
+	if (!get_fd)
+		get_fd = get_first_fd;
 
 	img = open_image(CR_FD_SK_QUEUES, O_RSTR);
 	if (!img)
@@ -314,7 +324,21 @@ int restore_sk_queue(int fd, unsigned int peer_id)
 			goto err;
 		}
 
-		ret = write(fd, buf, entry->length);
+		ret = fd = get_fd(sks, entry);
+		if (fd < 0) {
+			if (entry->has_sender_ino) {
+				pr_err("Can find sender with ino=%u\n", entry->sender_ino);
+				goto err;
+			}
+			if (noname_fd < 0)
+				noname_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+			if (noname_fd < 0) {
+				pr_err("Can't create socket\n");
+				goto err;
+			}
+			fd = noname_fd;
+		}
+		ret = sendto(fd, buf, entry->length, 0, dst_addr, dst_addrlen);
 		xfree(buf);
 		if (ret < 0) {
 			pr_perror("Failed to send packet");
@@ -330,6 +354,9 @@ int restore_sk_queue(int fd, unsigned int peer_id)
 		xfree(pkt);
 	}
 
+	if (noname_fd >= 0)
+		close(noname_fd);
+
 	close_image(img);
 	return 0;
 err:



More information about the CRIU mailing list