[CRIU] [PATCH 11/12] sk-queue: Allow to use several file descriptors to restore a queue
Kirill Tkhai
ktkhai at virtuozzo.com
Fri Apr 29 07:37:35 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 | 5 ++++-
criu/sk-queue.c | 43 ++++++++++++++++++++++++++++++++++++++-----
criu/sk-unix.c | 10 +++++-----
3 files changed, 47 insertions(+), 11 deletions(-)
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;
}
More information about the CRIU
mailing list