[CRIU] [PATCH v2 13/15] sk-queue: Allow to use several file descriptors to restore a queue
Kirill Tkhai
ktkhai at virtuozzo.com
Fri May 27 06:07:43 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 | 18 +++++++++++++++++-
criu/sk-queue.c | 37 ++++++++++++++++++++++++++++++++-----
2 files changed, 49 insertions(+), 6 deletions(-)
diff --git a/criu/include/sk-queue.h b/criu/include/sk-queue.h
index b7bb869..1b517c1 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,23 @@ 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, 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(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 *));
#endif /* __CR_SK_QUEUE_H__ */
diff --git a/criu/sk-queue.c b/criu/sk-queue.c
index 9a68286..2df708d 100644
--- a/criu/sk-queue.c
+++ b/criu/sk-queue.c
@@ -259,16 +259,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)
@@ -306,7 +316,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");
@@ -322,6 +346,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