[CRIU] [PATCH 1/9] unix: link a socket to its peer

Andrey Vagin avagin at openvz.org
Thu Dec 19 09:34:57 PST 2013


We are going to add callback-s for dumping external sockets.
All external sockets are added into unix_list, but for dumping we need
to know all peers.

And one more thing is that a socket is not closed before its peer is
not be dumped. We are going to transfer the socket decriptor in the
callback.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 sk-unix.c | 41 +++++++++++++++++++++++++++++++++++------
 1 file changed, 35 insertions(+), 6 deletions(-)

diff --git a/sk-unix.c b/sk-unix.c
index 54ed7ed..25ea1bb 100644
--- a/sk-unix.c
+++ b/sk-unix.c
@@ -45,6 +45,10 @@ struct unix_sk_desc {
 	gid_t			gid;
 
 	struct list_head	list;
+
+	int			fd;
+	struct list_head	peer_list;
+	struct list_head	peer_node;
 };
 
 static LIST_HEAD(unix_sockets);
@@ -121,7 +125,7 @@ static int can_dump_unix_sk(const struct unix_sk_desc *sk)
 
 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, *peer;
 	UnixSkEntry ue = UNIX_SK_ENTRY__INIT;
 	SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
 	FilePermsEntry perms = FILE_PERMS_ENTRY__INIT;
@@ -172,8 +176,6 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 	sk_encode_shutdown(&ue, sk->shutdown);
 
 	if (ue.peer) {
-		struct unix_sk_desc *peer;
-
 		peer = (struct unix_sk_desc *)lookup_socket(ue.peer, PF_UNIX, 0);
 		if (IS_ERR_OR_NULL(peer)) {
 			pr_err("Unix socket %#x without peer %#x\n",
@@ -197,9 +199,18 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 		 * It can be external socket, so we defer dumping
 		 * until all sockets the program owns are processed.
 		 */
-		if (!peer->sd.already_dumped && list_empty(&peer->list)) {
-			show_one_unix("Add a peer", peer);
-			list_add_tail(&peer->list, &unix_sockets);
+		if (!peer->sd.already_dumped) {
+			if (list_empty(&peer->list)) {
+				show_one_unix("Add a peer", peer);
+				list_add_tail(&peer->list, &unix_sockets);
+			}
+
+			list_add(&sk->peer_node, &peer->peer_list);
+			sk->fd = dup(lfd);
+			if (sk->fd < 0) {
+				pr_perror("Unable to dup(%d)", lfd);
+				goto err;
+			}
 		}
 
 		if ((ue.type != SOCK_DGRAM) && (
@@ -284,6 +295,13 @@ dump:
 	list_del_init(&sk->list);
 	sk->sd.already_dumped = 1;
 
+	while (!list_empty(&sk->peer_list)) {
+		struct unix_sk_desc *psk;
+		psk = list_first_entry(&sk->peer_list, struct unix_sk_desc, peer_node);
+		close_safe(&psk->fd);
+		list_del_init(&psk->peer_node);
+	}
+
 	return 0;
 
 err:
@@ -311,6 +329,10 @@ static int unix_collect_one(const struct unix_diag_msg *m,
 	d->state = m->udiag_state;
 	INIT_LIST_HEAD(&d->list);
 
+	INIT_LIST_HEAD(&d->peer_list);
+	INIT_LIST_HEAD(&d->peer_node);
+	d->fd = -1;
+
 	if (tb[UNIX_DIAG_SHUTDOWN])
 		d->shutdown = *(u8 *)RTA_DATA(tb[UNIX_DIAG_SHUTDOWN]);
 	else
@@ -495,6 +517,13 @@ int fix_external_unix_sockets(void)
 			goto err;
 
 		show_one_unix_img("Dumped extern", &e);
+
+		while (!list_empty(&sk->peer_list)) {
+			struct unix_sk_desc *psk;
+			psk = list_first_entry(&sk->peer_list, struct unix_sk_desc, peer_node);
+			close_safe(&psk->fd);
+			list_del_init(&psk->peer_node);
+		}
 	}
 
 	return 0;
-- 
1.8.3.1



More information about the CRIU mailing list