[11/12] sk-queue: Allow to use several file descriptors to restore a queue

Submitted by Kirill Tkhai on April 29, 2016, 2:37 p.m.

Details

Message ID 146194065366.9179.10310926060373749881.stgit@pro
State Rejected
Series "Support for packet's msg_name in receive queue of promiscous DGRAM sockets"
Headers show

Commit Message

Kirill Tkhai April 29, 2016, 2:37 p.m.
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@virtuozzo.com>
---
 criu/include/sk-queue.h |    5 ++++-
 criu/sk-queue.c         |   43 ++++++++++++++++++++++++++++++++++++++-----
 criu/sk-unix.c          |   10 +++++-----
 3 files changed, 47 insertions(+), 11 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/include/sk-queue.h b/criu/include/sk-queue.h
index b7bb869..a7ee5c1 100644
--- a/criu/include/sk-queue.h
+++ b/criu/include/sk-queue.h
@@ -8,9 +8,12 @@  struct sk_ino {
 	u32 ino;
 };
 
+#include "./images/sk-packet.pb-c.h"
+
 extern struct collect_image_info sk_queues_cinfo;
 extern int dump_sk_queue(int sock_fd, int sock_id, u32 (*get_sender)(const char *, int), u64 *sender_ino);
-extern int restore_sk_queue(int fd, unsigned int peer_id);
+extern int restore_sk_queue(int *fds, int num, int (*get_fd)(int *, int, SkPacketEntry *, struct sockaddr **,
+			    socklen_t *, void *data), unsigned int peer_id, void *data);
 extern int resolve_senders(unsigned int id, u32 ino, int (*add_receiver)(u32, struct sk_ino *));
 
 #endif /* __CR_SK_QUEUE_H__ */
diff --git a/criu/sk-queue.c b/criu/sk-queue.c
index 2802ecd..60263d4 100644
--- a/criu/sk-queue.c
+++ b/criu/sk-queue.c
@@ -259,16 +259,30 @@  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_elem(int *fd, int num, SkPacketEntry *pkt,
+			  struct sockaddr **addr, socklen_t *addrlen, void *data)
+{
+	*addr = NULL;
+	*addrlen = 0;
+
+	return fd[0];
+}
+
+int restore_sk_queue(int *fds, int num, int (*get_fd)(int *, int, SkPacketEntry *,
+		     struct sockaddr **, socklen_t *, void *), unsigned int peer_id, void *data)
 {
 	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; i < num; i++)
+		if (restore_prepare_socket(fds[i]))
+			return -1;
+
+	if (!get_fd)
+		get_fd = get_first_elem;
 
 	img = open_image(CR_FD_SK_QUEUES, O_RSTR);
 	if (!img)
@@ -276,6 +290,8 @@  int restore_sk_queue(int fd, unsigned int peer_id)
 
 	list_for_each_entry_safe(pkt, tmp, &packets_list, list) {
 		SkPacketEntry *entry = pkt->entry;
+		struct sockaddr *addr = NULL;
+		socklen_t addrlen = 0;
 		char *buf;
 
 		if (entry->id_for != peer_id)
@@ -306,7 +322,21 @@  int restore_sk_queue(int fd, unsigned int peer_id)
 			goto err;
 		}
 
-		ret = write(fd, buf, entry->length);
+		ret = fd = get_fd(fds, num, entry, &addr, &addrlen, data);
+		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)
+				fd = noname_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+			if (fd < 0) {
+				pr_err("Can't create socket\n");
+				goto err;
+			}
+		}
+		ret = sendto(fd, buf, entry->length, 0, addr, addrlen);
+		xfree(addr);
 		xfree(buf);
 		if (ret < 0) {
 			pr_perror("Failed to send packet");
@@ -322,6 +352,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:
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index f1890af..048d778 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -953,7 +953,7 @@  static int post_open_unix_sk(struct file_desc *d, int fd)
 
 	revert_unix_sk_cwd(&cwd_fd);
 
-	if (peer->queuer == ui->ue->ino && restore_sk_queue(fd, peer->ue->id))
+	if (peer->queuer == ui->ue->ino && restore_sk_queue(&fd, 1, NULL, peer->ue->id, NULL))
 		return -1;
 
 	if (rst_file_params(fd, ui->ue->fown, ui->ue->flags))
@@ -1056,9 +1056,9 @@  static int open_unixsk_pair_master(struct unix_sk_info *ui)
 		return -1;
 	}
 
-	if (restore_sk_queue(sk[0], peer->ue->id))
+	if (restore_sk_queue(&sk[0], 1, NULL, peer->ue->id, NULL))
 		return -1;
-	if (restore_sk_queue(sk[1], ui->ue->id))
+	if (restore_sk_queue(&sk[1], 1, NULL, ui->ue->id, NULL))
 		return -1;
 
 	if (bind_unix_sk(sk[0], ui))
@@ -1181,7 +1181,7 @@  static int open_unixsk_standalone(struct unix_sk_info *ui)
 		 * Restore queue at the one end,
 		 * before closing the second one.
 		 */
-		if (restore_sk_queue(sks[1], ui->ue->id)) {
+		if (restore_sk_queue(&sks[1], 1, NULL, ui->ue->id, NULL)) {
 			pr_perror("Can't restore socket queue");
 			return -1;
 		}
@@ -1217,7 +1217,7 @@  static int open_unixsk_standalone(struct unix_sk_info *ui)
 		 * This must be after the connect() hack, because
 		 * connect() flushes receive queue.
 		 */
-		if (restore_sk_queue(sks[1], ui->ue->id)) {
+		if (restore_sk_queue(&sks[1], 1, NULL, ui->ue->id, NULL)) {
 			pr_perror("Can't restore socket queue");
 			return -1;
 		}