[CRIU] [PATCH 2/9] sk-unix/dump: allocate UnixSkEntry dynamically

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


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

diff --git a/sk-unix.c b/sk-unix.c
index 25ea1bb..9fe3ef3 100644
--- a/sk-unix.c
+++ b/sk-unix.c
@@ -49,6 +49,8 @@ struct unix_sk_desc {
 	int			fd;
 	struct list_head	peer_list;
 	struct list_head	peer_node;
+
+	UnixSkEntry		*ue;
 };
 
 static LIST_HEAD(unix_sockets);
@@ -123,12 +125,46 @@ static int can_dump_unix_sk(const struct unix_sk_desc *sk)
 	return 1;
 }
 
+static int write_unix_entry(struct unix_sk_desc *sk)
+{
+	int ret;
+
+	ret = pb_write_one(fdset_fd(glob_fdset, CR_FD_UNIXSK), sk->ue, PB_UNIX_SK);
+
+	show_one_unix_img("Dumped", sk->ue);
+
+	release_skopts(sk->ue->opts);
+	xfree(sk->ue);
+
+	sk->ue = NULL;
+
+	return ret;
+}
+
 static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 {
 	struct unix_sk_desc *sk, *peer;
-	UnixSkEntry ue = UNIX_SK_ENTRY__INIT;
-	SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
-	FilePermsEntry perms = FILE_PERMS_ENTRY__INIT;
+	UnixSkEntry *ue;
+	SkOptsEntry *skopts;
+	FilePermsEntry *perms;
+	FownEntry *fown;
+
+	ue = xmalloc(sizeof(UnixSkEntry) +
+			sizeof(SkOptsEntry) +
+			sizeof(FilePermsEntry) +
+			sizeof(FownEntry));
+	if (ue == NULL)
+		return -1;
+
+	skopts = (SkOptsEntry *) ue + sizeof(UnixSkEntry);
+	perms = (FilePermsEntry *) skopts + sizeof(SkOptsEntry);
+	fown = (FownEntry *) perms + sizeof(FilePermsEntry);
+
+	unix_sk_entry__init(ue);
+	sk_opts_entry__init(skopts);
+	file_perms_entry__init(perms);
+
+	*fown = p->fown;
 
 	sk = (struct unix_sk_desc *)lookup_socket(p->stat.st_ino, PF_UNIX, 0);
 	if (IS_ERR_OR_NULL(sk)) {
@@ -141,45 +177,45 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 
 	BUG_ON(sk->sd.already_dumped);
 
-	ue.name.len	= (size_t)sk->namelen;
-	ue.name.data	= (void *)sk->name;
+	ue->name.len	= (size_t)sk->namelen;
+	ue->name.data	= (void *)sk->name;
 
-	ue.id		= id;
-	ue.ino		= sk->sd.ino;
-	ue.type		= sk->type;
-	ue.state	= sk->state;
-	ue.flags	= p->flags;
-	ue.backlog	= sk->wqlen;
-	ue.peer		= sk->peer_ino;
-	ue.fown		= (FownEntry *)&p->fown;
-	ue.opts		= &skopts;
-	ue.uflags	= 0;
+	ue->id		= id;
+	ue->ino		= sk->sd.ino;
+	ue->type	= sk->type;
+	ue->state	= sk->state;
+	ue->flags	= p->flags;
+	ue->backlog	= sk->wqlen;
+	ue->peer	= sk->peer_ino;
+	ue->fown	= fown;
+	ue->opts	= skopts;
+	ue->uflags	= 0;
 
 	/*
 	 * Check if this socket is connected to criu service.
 	 * Dump it like closed one and mark it for restore.
 	 */
-	if (unlikely(ue.peer == service_sk_ino)) {
-		ue.state = TCP_CLOSE;
-		ue.peer = 0;
-		ue.uflags |= USK_SERVICE;
+	if (unlikely(ue->peer == service_sk_ino)) {
+		ue->state = TCP_CLOSE;
+		ue->peer = 0;
+		ue->uflags |= USK_SERVICE;
 	}
 
 	if (sk->namelen && *sk->name) {
-		ue.file_perms = &perms;
+		ue->file_perms = perms;
 
-		perms.mode	= sk->mode;
-		perms.uid	= sk->uid;
-		perms.gid	= sk->gid;
+		perms->mode	= sk->mode;
+		perms->uid	= sk->uid;
+		perms->gid	= sk->gid;
 	}
 
-	sk_encode_shutdown(&ue, sk->shutdown);
+	sk_encode_shutdown(ue, sk->shutdown);
 
-	if (ue.peer) {
-		peer = (struct unix_sk_desc *)lookup_socket(ue.peer, PF_UNIX, 0);
+	if (ue->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",
-					ue.ino, ue.peer);
+					ue->ino, ue->peer);
 			goto err;
 		}
 
@@ -187,10 +223,10 @@ static int dump_one_unix_fd(int lfd, u32 id, const 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.ino) {
+		if (peer->peer_ino != ue->ino) {
 			if (!peer->name) {
 				pr_err("Unix socket %#x with unreachable peer %#x (%#x/%s)\n",
-				       ue.ino, ue.peer, peer->peer_ino, peer->name);
+				       ue->ino, ue->peer, peer->peer_ino, peer->name);
 				goto err;
 			}
 		}
@@ -213,25 +249,25 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 			}
 		}
 
-		if ((ue.type != SOCK_DGRAM) && (
-				((ue.shutdown == SK_SHUTDOWN__READ)  &&
+		if ((ue->type != SOCK_DGRAM) && (
+				((ue->shutdown == SK_SHUTDOWN__READ)  &&
 				 (peer->shutdown != SK_SHUTDOWN__WRITE)) ||
-				((ue.shutdown == SK_SHUTDOWN__WRITE) &&
+				((ue->shutdown == SK_SHUTDOWN__WRITE) &&
 				 (peer->shutdown != SK_SHUTDOWN__READ))  ||
-				((ue.shutdown == SK_SHUTDOWN__BOTH)  &&
+				((ue->shutdown == SK_SHUTDOWN__BOTH)  &&
 				 (peer->shutdown != SK_SHUTDOWN__BOTH)) )) {
 			/*
 			 * On restore we assume, that stream pairs must
 			 * be shut down from one end only
 			 */
 			pr_err("Shutdown mismatch %u:%d -> %u:%d\n",
-					ue.ino, ue.shutdown, peer->sd.ino, peer->shutdown);
+					ue->ino, ue->shutdown, peer->sd.ino, peer->shutdown);
 			goto err;
 		}
-	} else if (ue.state == TCP_ESTABLISHED) {
+	} else if (ue->state == TCP_ESTABLISHED) {
 		const struct unix_sk_listen_icon *e;
 
-		e = lookup_unix_listen_icons(ue.ino);
+		e = lookup_unix_listen_icons(ue->ino);
 		if (!e) {
 			/*
 			 * ESTABLISHED socket without peer and without
@@ -239,12 +275,12 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 			 * connection.
 			 */
 
-			if (ue.shutdown == SK_SHUTDOWN__BOTH) {
+			if (ue->shutdown == SK_SHUTDOWN__BOTH) {
 				pr_info("Dumping semi-closed connection\n");
 				goto dump;
 			}
 
-			pr_err("Dangling connection %#x\n", ue.ino);
+			pr_err("Dangling connection %#x\n", ue->ino);
 			goto err;
 		}
 
@@ -260,22 +296,20 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 		/* 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.ino);
+				"non-listening socket %d\n", ue->ino);
 			goto err;
 		}
 
-		ue.peer = e->sk_desc->sd.ino;
+		ue->peer = e->sk_desc->sd.ino;
 
 		pr_debug("\t\tFixed inflight socket %#x peer %#x)\n",
-				ue.ino, ue.peer);
+				ue->ino, ue->peer);
 	}
 dump:
-	if (dump_socket_opts(lfd, &skopts))
-		goto err;
-
-	if (pb_write_one(fdset_fd(glob_fdset, CR_FD_UNIXSK), &ue, PB_UNIX_SK))
+	if (dump_socket_opts(lfd, skopts))
 		goto err;
 
+	sk->ue = ue;
 	/*
 	 * If a stream listening socket has non-zero rqueue, this
 	 * means there are in-flight connections waiting to get
@@ -284,13 +318,14 @@ dump:
 	 */
 	if (sk->rqlen != 0 && !(sk->type == SOCK_STREAM &&
 				sk->state == TCP_LISTEN))
-		if (dump_sk_queue(lfd, ue.id))
+		if (dump_sk_queue(lfd, ue->id))
 			goto err;
 
 	pr_info("Dumping unix socket at %d\n", p->fd);
 	show_one_unix("Dumping", sk);
-	show_one_unix_img("Dumped", &ue);
-	release_skopts(&skopts);
+
+	if (write_unix_entry(sk))
+		goto err;
 
 	list_del_init(&sk->list);
 	sk->sd.already_dumped = 1;
@@ -305,7 +340,8 @@ dump:
 	return 0;
 
 err:
-	release_skopts(&skopts);
+	release_skopts(skopts);
+	xfree(ue);
 	return -1;
 }
 
-- 
1.8.3.1



More information about the CRIU mailing list