[CRIU] [PATCH] unix: allow --external unix[ino]:stub[string]

Ruslan Kuprieiev rkuprieiev at cloudlinux.com
Tue Feb 28 05:47:05 PST 2017


Needles to say it's useful for debug, but it is also
very useful when you syncronise checkpoint/restore
whith a dumpee using unix socketpair and want it to
painlessly receive notification on restore.

I.e. on dump, if --external unix[ino]:foo is specified,
criu will treat specified unix socket almost the same
way it handles criu service socket. It will dump it as
closed and will put "foo" string into images, to put
that "foo" string into that socket on restore. This is
almost identical to what criu does with service socket,
but instead of putting a Criu_Resp message into it on
restore, it puts an arbitrary string.

Signed-off-by: Ruslan Kuprieiev <rkuprieiev at cloudlinux.com>
---
 criu/crtools.c          |  2 +-
 criu/external.c         | 26 ++++++++++++++++++++++++++
 criu/include/external.h |  1 +
 criu/sk-unix.c          | 25 +++++++++++++++++++++++--
 images/sk-unix.proto    |  1 +
 5 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/criu/crtools.c b/criu/crtools.c
index ec02fe3..4bb3c69 100644
--- a/criu/crtools.c
+++ b/criu/crtools.c
@@ -884,7 +884,7 @@ usage:
 "                            tty[rdev:dev]\n"
 "                            file[mnt_id:inode]\n"
 "                            dev[major/minor]:NAME\n"
-"                            unix[ino]\n"
+"                            unix[ino]{:stub[string]}\n"
 "                            mnt[MOUNTPOINT]:COOKIE\n"
 "                            mnt[]{:AUTO_OPTIONS}\n"
 "                        Formats of RES on restore:\n"
diff --git a/criu/external.c b/criu/external.c
index 96e6768..721102d 100644
--- a/criu/external.c
+++ b/criu/external.c
@@ -73,6 +73,32 @@ char *external_lookup_by_key(char *key)
 	return ERR_PTR(-ENOENT);
 }
 
+char *external_lookup_stub_by_key(char *key)
+{
+	char *val, *stub, *end;
+	char prefix[] = "stub[";
+	char suffix = ']';
+
+	val = external_lookup_by_key(key);
+	if (IS_ERR_OR_NULL(val))
+		return val;
+
+	if (strncmp(val, prefix, strlen(prefix)))
+		return ERR_PTR(-ENOENT);
+
+	val += strlen(prefix);
+	stub = strdup(val);
+
+	end = strrchr(stub, suffix);
+	if (!end) {
+		free(stub);
+		return ERR_PTR(-EINVAL);
+	}
+	*end = '\0';
+
+	return stub;
+}
+
 int external_for_each_type(char *type, int (*cb)(struct external *, void *), void *arg)
 {
 	struct external *ext;
diff --git a/criu/include/external.h b/criu/include/external.h
index d284b79..08e04e4 100644
--- a/criu/include/external.h
+++ b/criu/include/external.h
@@ -9,6 +9,7 @@ struct external {
 extern int add_external(char *key);
 extern bool external_lookup_id(char *id);
 extern char *external_lookup_by_key(char *id);
+extern char *external_lookup_stub_by_key(char *id);
 extern void *external_lookup_data(char *id);
 extern int external_for_each_type(char *type, int (*cb)(struct external *, void *), void *arg);
 
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index a44d998..419c061 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -263,6 +263,8 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 	SkOptsEntry *skopts;
 	FilePermsEntry *perms;
 	FownEntry *fown;
+	char buf[PATH_MAX];
+	char *stub = NULL;
 
 	ue = xmalloc(sizeof(UnixSkEntry) +
 			sizeof(SkOptsEntry) +
@@ -324,6 +326,18 @@ static int dump_one_unix_fd(int lfd, u32 id, const struct fd_parms *p)
 		ue->uflags |= USK_SERVICE;
 	}
 
+	/* Same as with service_sk, but for custom sockets */
+	snprintf(buf, sizeof(buf), "unix[%u]", ue->ino);
+	stub = external_lookup_stub_by_key(buf);
+	if (unlikely(!IS_ERR_OR_NULL(stub))) {
+		pr_info("Unix socket %#x is closed and plugged with stub '%s' "
+			"for restore\n", ue->ino, stub);
+		ue->state = TCP_CLOSE;
+		ue->peer = 0;
+		ue->uflags |= USK_SERVICE;
+		ue->stub = (void *)stub;
+	}
+
 	if (sk->namelen && *sk->name) {
 		ue->file_perms = perms;
 
@@ -1165,8 +1179,15 @@ static int open_unixsk_standalone(struct unix_sk_info *ui, int *new_fd)
 			return -1;
 		}
 
-		if (send_criu_dump_resp(sks[1], true, true) == -1)
-			return -1;
+		if (ui->ue->stub) {
+			pr_warn("Writing stub %s to unix socket %#x\n",
+				(char *)ui->ue->stub, ui->ue->ino);
+			if (write(sks[1], ui->ue->stub, strlen(ui->ue->stub)) != strlen(ui->ue->stub))
+				return -1;
+		} else {
+			if (send_criu_dump_resp(sks[1], true, true) == -1)
+				return -1;
+		}
 
 		close(sks[1]);
 		sk = sks[0];
diff --git a/images/sk-unix.proto b/images/sk-unix.proto
index d695070..a1ce8be 100644
--- a/images/sk-unix.proto
+++ b/images/sk-unix.proto
@@ -50,4 +50,5 @@ message unix_sk_entry {
 	optional bool			deleted		= 15;
 
 	optional uint32			ns_id		= 16;
+	optional string			stub		= 17;
 }
-- 
2.9.3



More information about the CRIU mailing list