[CRIU] [PATCH v2 10/15] unix: Resolve senders of packets in receive queue of DGRAM socket
Kirill Tkhai
ktkhai at virtuozzo.com
Fri May 27 06:07:16 PDT 2016
Determine unique senders of packets in receive queue, and notify
every of them, that it has a receiver. Link the receiver ino in
unix_sk_info::receivers list of the sender.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/include/sk-queue.h | 6 +++++
criu/sk-queue.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
criu/sk-unix.c | 37 +++++++++++++++++++++++++++++++
3 files changed, 99 insertions(+)
diff --git a/criu/include/sk-queue.h b/criu/include/sk-queue.h
index 93498e3..b7bb869 100644
--- a/criu/include/sk-queue.h
+++ b/criu/include/sk-queue.h
@@ -3,8 +3,14 @@
#define SK_NONAME_SENDER (~0ULL)
+struct sk_ino {
+ struct list_head list;
+ u32 ino;
+};
+
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 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 fa3407b..9a68286 100644
--- a/criu/sk-queue.c
+++ b/criu/sk-queue.c
@@ -17,6 +17,7 @@
#include "servicefd.h"
#include "cr_options.h"
#include "util.h"
+#include "rst-malloc.h"
#include "util-pie.h"
#include "sockets.h"
@@ -203,6 +204,61 @@ int dump_sk_queue(int sock_fd, int sock_id, u32 (*get_sender)(const char *, int)
return ret;
}
+int resolve_senders(unsigned int id, u32 ino, int (*add_receiver)(u32, struct sk_ino *))
+{
+ struct sk_ino *si, *tmp;
+ struct sk_packet *pkt;
+ u32 sender_ino;
+ LIST_HEAD(head);
+ int count = 0;
+
+ list_for_each_entry(pkt, &packets_list, list) {
+ SkPacketEntry *entry = pkt->entry;
+ bool found = false;
+
+ if (entry->id_for != id)
+ continue;
+ if (!entry->has_sender_ino)
+ continue;
+
+ sender_ino = entry->sender_ino;
+
+ list_for_each_entry(si, &head, list) {
+ if (si->ino == sender_ino) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ si = shmalloc(sizeof(*si));
+ if (!si)
+ goto err;
+ si->ino = sender_ino;
+ list_add_tail(&si->list, &head);
+ count++;
+ }
+
+ list_for_each_entry_safe(si, tmp, &head, list) {
+ list_del(&si->list);
+
+ sender_ino = si->ino;
+ si->ino = ino; /* Reuse it as receiver */
+
+ if (add_receiver(sender_ino, si) < 0) {
+ list_add(&si->list, &head);
+ goto err;
+ }
+ }
+
+ return count;
+err:
+ pr_err("Resolving senders failed\n");
+ return -1;
+}
+
int restore_sk_queue(int fd, unsigned int peer_id)
{
struct sk_packet *pkt, *tmp;
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index cf589b8..fc3cb44 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -833,6 +833,7 @@ int fix_external_unix_sockets(void)
struct unix_sk_info {
UnixSkEntry *ue;
struct list_head list;
+ struct list_head receivers;
char *name;
char *name_dir;
unsigned flags;
@@ -852,6 +853,8 @@ struct unix_sk_info {
* that should do the queueing.
*/
u32 queuer;
+
+ u32 nr_senders;
};
#define USK_PAIR_MASTER 0x1
@@ -1058,6 +1061,8 @@ static int open_unixsk_pair_master(struct unix_sk_info *ui)
struct unix_sk_info *peer = ui->peer;
struct fdinfo_list_entry *fle;
+ BUG_ON(ui->nr_senders);
+
pr_info("Opening pair master (id %#x ino %#x peer %#x)\n",
ui->ue->id, ui->ue->ino, ui->ue->peer);
@@ -1106,6 +1111,8 @@ static int open_unixsk_pair_slave(struct unix_sk_info *ui)
struct fdinfo_list_entry *fle;
int sk;
+ BUG_ON(ui->nr_senders);
+
fle = file_master(&ui->d);
pr_info("Opening pair slave (id %#x ino %#x peer %#x) on %d\n",
@@ -1368,6 +1375,8 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base, struct cr_img *i)
futex_init(&ui->prepared);
ui->queuer = 0;
+ INIT_LIST_HEAD(&ui->receivers);
+ ui->nr_senders = 0;
ui->peer = NULL;
ui->flags = 0;
pr_info(" `- Got %#x peer %#x (name %s dir %s)\n",
@@ -1406,6 +1415,22 @@ static u32 sk_queuer(struct unix_sk_info *sk, struct unix_sk_info *maybe_queuer)
return 0;
}
+static int unix_add_receiver(u32 ino, struct sk_ino *si)
+{
+ struct unix_sk_info *ui;
+
+ ui = find_unix_sk_by_ino(ino);
+ if (!ui) {
+ pr_err("Can't find a sender: ino=%d\n", ino);
+ return -1;
+ }
+
+ list_add(&si->list, &ui->receivers);
+ pr_info("Add receiver %d to %u\n", si->ino, ino);
+
+ return 0;
+}
+
static int resolve_unix_peers(void *unused)
{
struct unix_sk_info *ui, *peer;
@@ -1459,6 +1484,18 @@ static int resolve_unix_peers(void *unused)
}
}
+ list_for_each_entry(ui, &unix_sockets, list) {
+ if (ui->ue->type != SOCK_DGRAM || ui->queuer ||
+ (ui->ue->uflags & (USK_EMPTY_Q|USK_NONAME_SND|USK_EXTERN)))
+ continue;
+
+ ui->nr_senders = resolve_senders(ui->ue->id, ui->ue->ino, unix_add_receiver);
+ pr_info("Found a socket w/o queuer: ino=%d, senders=%d\n",
+ ui->ue->ino, ui->nr_senders);
+ if (ui->nr_senders < 0)
+ return -1;
+ }
+
pr_info("Unix sockets:\n");
list_for_each_entry(ui, &unix_sockets, list) {
struct fdinfo_list_entry *fle;
More information about the CRIU
mailing list