[CRIU] [RFC] sockets, unix: Use general machnism for checkpoint/restore

Cyrill Gorcunov gorcunov at openvz.org
Fri May 11 12:20:45 EDT 2012


Pavel, tell me please how the attached patch looks for you.
If it's ok I'll continue with other socket types.

	Cyrill
-------------- next part --------------
>From 15b5c6309dfdac177c750d2491431136e32bd5a0 Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Fri, 11 May 2012 20:19:02 +0400
Subject: [PATCH] sockets, unix: Use general machnism for checkpoint/restore

Use fdtype_ops facility to c/r unix sockets.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 files.c           |   21 +++++++++++
 include/files.h   |    4 ++
 include/image.h   |    1 +
 include/sockets.h |    3 +-
 sk-unix.c         |   96 ++++++++++++++++++++++++++++++----------------------
 sockets.c         |   19 +++++++---
 6 files changed, 95 insertions(+), 49 deletions(-)

diff --git a/files.c b/files.c
index 6ca1978..5a43580 100644
--- a/files.c
+++ b/files.c
@@ -56,6 +56,27 @@ void file_desc_add(struct file_desc *d, u32 id,
 	list_add_tail(&d->hash, &file_descs[id % FDESC_HASH_SIZE]);
 }
 
+struct file_desc *
+find_file_desc_slow_by(int type, void *p,
+		       int (*cb)(struct file_desc *d, void *p))
+{
+	struct file_desc *d;
+	struct list_head *chain;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(file_descs); i++) {
+		chain = &file_descs[i];
+		list_for_each_entry(d, chain, hash) {
+			if (d->ops->type == type) {
+				if (cb(d, p))
+					return d;
+			}
+		}
+	}
+
+	return NULL;
+}
+
 struct file_desc *find_file_desc_raw(int type, u32 id)
 {
 	struct file_desc *d;
diff --git a/include/files.h b/include/files.h
index 2e97c76..662b4ab 100644
--- a/include/files.h
+++ b/include/files.h
@@ -55,6 +55,10 @@ struct fdtype_ops {
 	int		(*dump)(int lfd, u32 id, const struct fd_parms *p);
 };
 
+extern struct file_desc *
+find_file_desc_slow_by(int type, void *p,
+		       int (*cb)(struct file_desc *d, void *p));
+
 extern u32 make_gen_id(const struct fd_parms *p);
 struct cr_fdset;
 extern int do_dump_gen_file(struct fd_parms *p, int lfd,
diff --git a/include/image.h b/include/image.h
index 650ebf1..e004dd4 100644
--- a/include/image.h
+++ b/include/image.h
@@ -177,6 +177,7 @@ struct sk_opts_entry {
 
 struct unix_sk_entry {
 	u32	id;
+	u32	ino;
 	u8	type;
 	u8	state;
 	u8	namelen; /* fits UNIX_PATH_MAX */
diff --git a/include/sockets.h b/include/sockets.h
index b94fab4..d683960 100644
--- a/include/sockets.h
+++ b/include/sockets.h
@@ -49,8 +49,7 @@ extern struct socket_desc *lookup_socket(int ino);
 
 extern int dump_one_inet(struct socket_desc *_sk, struct fd_parms *p,
 			 int lfd, const struct cr_fdset *cr_fdset);
-extern int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
-			 int lfd, const struct cr_fdset *cr_fdset);
+extern int dump_one_unix(struct fd_parms *p, int lfd, const struct cr_fdset *set);
 
 extern int inet_collect_one(struct nlmsghdr *h, int family, int type, int proto);
 extern int unix_receive_one(struct nlmsghdr *h);
diff --git a/sk-unix.c b/sk-unix.c
index 193b12e..0c8153d 100644
--- a/sk-unix.c
+++ b/sk-unix.c
@@ -11,6 +11,7 @@
 #include "crtools.h"
 #include "unix_diag.h"
 #include "files.h"
+#include "file-ids.h"
 #include "image.h"
 #include "log.h"
 #include "util.h"
@@ -72,8 +73,8 @@ static void show_one_unix(char *act, const struct unix_sk_desc *sk)
 
 static void show_one_unix_img(const char *act, const struct unix_sk_entry *e)
 {
-	pr_info("\t%s: id 0x%x peer 0x%x type %d state %d name %d bytes\n",
-		act, e->id, e->peer, e->type, e->state, e->namelen);
+	pr_info("\t%s: id 0x%x ino 0x%x peer 0x%x type %d state %d name %d bytes\n",
+		act, e->id, e->ino, e->peer, e->type, e->state, e->namelen);
 }
 
 static int can_dump_unix_sk(const struct unix_sk_desc *sk)
@@ -104,28 +105,24 @@ static int can_dump_unix_sk(const struct unix_sk_desc *sk)
 	return 1;
 }
 
-int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
-		int lfd, const struct cr_fdset *cr_fdset)
+static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 {
-	struct unix_sk_desc *sk = (struct unix_sk_desc *)_sk;
+	struct unix_sk_desc *sk;
 	struct fdinfo_entry fe;
 	struct unix_sk_entry ue;
 
-	if (!can_dump_unix_sk(sk))
+	sk = (struct unix_sk_desc *)lookup_socket(p->stat.st_ino);
+	if (!sk)
 		goto err;
 
-	fe.fd = p->fd;
-	fe.type = FDINFO_UNIXSK;
-	fe.id = sk->sd.ino;
-	fe.flags = p->fd_flags;
-
-	if (write_img(fdset_fd(cr_fdset, CR_FD_FDINFO), &fe))
+	if (!can_dump_unix_sk(sk))
 		goto err;
 
 	if (sk->sd.already_dumped)
 		return 0;
 
-	ue.id		= sk->sd.ino;
+	ue.id		= id;
+	ue.ino		= sk->sd.ino;
 	ue.type		= sk->type;
 	ue.state	= sk->state;
 	ue.namelen	= sk->namelen;
@@ -141,7 +138,7 @@ int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
 		peer = (struct unix_sk_desc *)lookup_socket(ue.peer);
 		if (!peer) {
 			pr_err("Unix socket %#x without peer %#x\n",
-					ue.id, ue.peer);
+					ue.ino, ue.peer);
 			goto err;
 		}
 
@@ -149,10 +146,10 @@ int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
 		 * Peer should have us as peer or have a name by which
 		 * we can access one.
 		 */
-		if (peer->peer_ino != ue.id) {
+		if (peer->peer_ino != ue.ino) {
 			if (!peer->name) {
 				pr_err("Unix socket %#x with unreachable peer %#x (%#x/%s)\n",
-				       ue.id, ue.peer, peer->peer_ino, peer->name);
+				       ue.ino, ue.peer, peer->peer_ino, peer->name);
 				goto err;
 			}
 
@@ -175,23 +172,23 @@ int dump_one_unix(const struct socket_desc *_sk, struct fd_parms *p,
 		 * not now, just to reduce size of dump files.
 		 */
 
-		e = lookup_unix_listen_icons(ue.id);
+		e = lookup_unix_listen_icons(ue.ino);
 		if (!e) {
-			pr_err("Dangling in-flight connection %d\n", ue.id);
+			pr_err("Dangling in-flight connection %d\n", ue.ino);
 			goto err;
 		}
 
 		/* e->sk_desc is _never_ NULL */
 		if (e->sk_desc->state != TCP_LISTEN) {
 			pr_err("In-flight connection on "
-				"non-listening socket %d\n", ue.id);
+				"non-listening socket %d\n", ue.ino);
 			goto err;
 		}
 
 		ue.peer = e->sk_desc->sd.ino;
 
 		pr_debug("\t\tFixed inflight socket %#x peer %#x)\n",
-				ue.id, ue.peer);
+				ue.ino, ue.peer);
 	}
 
 	if (dump_socket_opts(lfd, &ue.opts))
@@ -219,6 +216,17 @@ err:
 	return -1;
 }
 
+static const struct fdtype_ops unix_dump_ops = {
+	.type		= FDINFO_UNIXSK,
+	.make_gen_id	= make_gen_id,
+	.dump		= dump_one_unix_fd,
+};
+
+int dump_one_unix(struct fd_parms *p, int lfd, const struct cr_fdset *set)
+{
+	return do_dump_gen_file(p, lfd, &unix_dump_ops, set);
+}
+
 static int unix_collect_one(const struct unix_diag_msg *m,
 		struct rtattr **tb)
 {
@@ -384,7 +392,8 @@ int fix_external_unix_sockets(void)
 			goto err;
 		}
 
-		e.id		= sk->sd.ino;
+		e.id		= fd_id_generate_special();
+		e.ino		= sk->sd.ino;
 		e.type		= SOCK_DGRAM;
 		e.state		= TCP_LISTEN;
 		e.namelen	= sk->namelen;
@@ -419,11 +428,16 @@ struct unix_sk_info {
 #define USK_PAIR_MASTER		0x1
 #define USK_PAIR_SLAVE		0x2
 
-static struct unix_sk_info *find_unix_sk(int id)
+static int find_unix_sk_cb(struct file_desc *d, void *p)
 {
-	struct file_desc *d;
+	struct unix_sk_info *ui = container_of(d, struct unix_sk_info, d);
+	return ui->ue.ino == (u32)(long)p;
+}
 
-	d = find_file_desc_raw(FDINFO_UNIXSK, id);
+static struct unix_sk_info *find_unix_sk(int ino)
+{
+	struct file_desc *d;
+	d = find_file_desc_slow_by(FDINFO_UNIXSK, (void *)(long)ino, find_unix_sk_cb);
 	if (d)
 		return container_of(d, struct unix_sk_info, d);
 	return NULL;
@@ -441,8 +455,8 @@ void show_unixsk(int fd, struct cr_options *o)
 		if (ret <= 0)
 			goto out;
 
-		pr_msg("id 0x%8x type %s state %s namelen %4d backlog %4d peer 0x%8x flags 0x%2x uflags 0x%2x",
-			ue.id, sktype2s(ue.type), skstate2s(ue.state),
+		pr_msg("id 0x%8x ino 0x%8x type %s state %s namelen %4d backlog %4d peer 0x%8x flags 0x%2x uflags 0x%2x",
+			ue.id, ue.ino, sktype2s(ue.type), skstate2s(ue.state),
 			ue.namelen, ue.backlog, ue.peer, ue.flags, ue.uflags);
 
 		if (ue.namelen) {
@@ -501,7 +515,7 @@ int run_unix_connections(void)
 		struct fdinfo_list_entry *fle;
 		struct sockaddr_un addr;
 
-		pr_info("\tConnect %#x to %#x\n", ui->ue.id, peer->ue.id);
+		pr_info("\tConnect %#x to %#x\n", ui->ue.ino, peer->ue.ino);
 
 		fle = file_master(&ui->d);
 
@@ -518,7 +532,7 @@ try_again:
 				goto try_again; /* FIXME use futex waiters */
 			}
 
-			pr_perror("Can't connect %#x socket", ui->ue.id);
+			pr_perror("Can't connect %#x socket", ui->ue.ino);
 			return -1;
 		}
 
@@ -579,8 +593,8 @@ static int open_unixsk_pair_master(struct unix_sk_info *ui)
 	struct unix_sk_info *peer = ui->peer;
 	struct fdinfo_list_entry *fle;
 
-	pr_info("Opening pair master (id %#x peer %#x)\n",
-			ui->ue.id, ui->ue.peer);
+	pr_info("Opening pair master (id %#x ino %#x peer %#x)\n",
+			ui->ue.id, ui->ue.ino, ui->ue.peer);
 
 	if (socketpair(PF_UNIX, ui->ue.type, 0, sk) < 0) {
 		pr_perror("Can't make socketpair");
@@ -623,8 +637,8 @@ static int open_unixsk_pair_slave(struct unix_sk_info *ui)
 
 	fle = file_master(&ui->d);
 
-	pr_info("Opening pair slave (id %#x peer %#x) on %d\n",
-			ui->ue.id, ui->ue.peer, fle->fe.fd);
+	pr_info("Opening pair slave (id %#x ino %#x peer %#x) on %d\n",
+			ui->ue.id, ui->ue.ino, ui->ue.peer, fle->fe.fd);
 
 	sk = recv_fd(fle->fe.fd);
 	if (sk < 0) {
@@ -649,8 +663,8 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
 {
 	int sk;
 
-	pr_info("Opening standalone socket (id %#x peer %#x)\n",
-			ui->ue.id, ui->ue.peer);
+	pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n",
+			ui->ue.id, ui->ue.ino, ui->ue.peer);
 
 	sk = socket(PF_UNIX, ui->ue.type, 0);
 	if (sk < 0) {
@@ -662,7 +676,7 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
 		return -1;
 
 	if (ui->ue.state == TCP_LISTEN) {
-		pr_info("\tPutting %#x into listen state\n", ui->ue.id);
+		pr_info("\tPutting %#x into listen state\n", ui->ue.ino);
 		if (listen(sk, ui->ue.backlog) < 0) {
 			pr_perror("Can't make usk listen");
 			return -1;
@@ -675,7 +689,7 @@ static int open_unixsk_standalone(struct unix_sk_info *ui)
 			return -1;
 
 	} else if (ui->peer) {
-		pr_info("\tWill connect %#x to %#x later\n", ui->ue.id, ui->ue.peer);
+		pr_info("\tWill connect %#x to %#x later\n", ui->ue.ino, ui->ue.peer);
 		if (schedule_conn_job(ui))
 			return -1;
 	}
@@ -758,7 +772,7 @@ int collect_unix_sockets(void)
 
 		ui->peer = NULL;
 		ui->flags = 0;
-		pr_info(" `- Got 0x%x peer 0x%x\n", ui->ue.id, ui->ue.peer);
+		pr_info(" `- Got 0x%x peer 0x%x\n", ui->ue.ino, ui->ue.peer);
 		file_desc_add(&ui->d, ui->ue.id, &unix_desc_ops);
 		list_add_tail(&ui->list, &unix_sockets);
 	}
@@ -792,7 +806,7 @@ int resolve_unix_peers(void)
 
 		if (!peer) {
 			pr_err("FATAL: Peer %#x unresolved for %#x\n",
-					ui->ue.peer, ui->ue.id);
+					ui->ue.peer, ui->ue.ino);
 			return -1;
 		}
 
@@ -800,7 +814,7 @@ int resolve_unix_peers(void)
 		if (ui == peer)
 			/* socket connected to self %) */
 			continue;
-		if (peer->ue.peer != ui->ue.id)
+		if (peer->ue.peer != ui->ue.ino)
 			continue;
 
 		/* socketpair or interconnected sockets */
@@ -830,8 +844,8 @@ int resolve_unix_peers(void)
 	list_for_each_entry(ui, &unix_sockets, list) {
 		struct fdinfo_list_entry *fle;
 
-		pr_info("\t%#x -> %#x (%#x) flags %#x\n", ui->ue.id, ui->ue.peer,
-				ui->peer ? ui->peer->ue.id : 0, ui->flags);
+		pr_info("\t%#x -> %#x (%#x) flags %#x\n", ui->ue.ino, ui->ue.peer,
+				ui->peer ? ui->peer->ue.ino : 0, ui->flags);
 		list_for_each_entry(fle, &ui->d.fd_info_head, desc_list)
 			pr_info("\t\tfd %d in pid %d\n",
 					fle->fe.fd, fle->pid);
diff --git a/sockets.c b/sockets.c
index 260e941..d9732c1 100644
--- a/sockets.c
+++ b/sockets.c
@@ -42,7 +42,7 @@ static char buf[4096];
 
 static struct socket_desc *sockets[SK_HASH_SIZE];
 
-struct socket_desc *lookup_socket(int ino)
+static struct socket_desc *__lookup_socket(int ino)
 {
 	struct socket_desc *sd;
 
@@ -52,6 +52,16 @@ struct socket_desc *lookup_socket(int ino)
 	return NULL;
 }
 
+struct socket_desc *lookup_socket(int ino)
+{
+	struct socket_desc *sk;
+
+	sk = __lookup_socket(ino);
+	if (!sk)
+		pr_err("Uncollected socket 0x%8x\n", ino);
+	return sk;
+}
+
 int sk_collect_one(int ino, int family, struct socket_desc *d)
 {
 	struct socket_desc **chain;
@@ -125,16 +135,13 @@ int dump_socket_opts(int sk, struct sk_opts_entry *soe)
 int dump_socket(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset)
 {
 	struct socket_desc *sk;
-
 	sk = lookup_socket(p->stat.st_ino);
-	if (!sk) {
-		pr_err("Uncollected socket 0x%8x\n", (int)p->stat.st_ino);
+	if (!sk)
 		return -1;
-	}
 
 	switch (sk->family) {
 	case AF_UNIX:
-		return dump_one_unix(sk, p, lfd, cr_fdset);
+		return dump_one_unix(p, lfd, cr_fdset);
 	case AF_INET:
 	case AF_INET6:
 		return dump_one_inet(sk, p, lfd, cr_fdset);
-- 
1.7.7.6



More information about the CRIU mailing list