[CRIU] [PATCH 3/4] sk-unix: Handle bindmounted dgram sockets on restore

Cyrill Gorcunov gorcunov at openvz.org
Tue Aug 8 14:25:09 MSK 2017


If a socket is bindmounted one we open it early (thus mount engine
will be eable to proceed), put it into fdstore and then simply fetch
it from there.

Note it's important that only basic scenario with dgram/closed sockets
is supported by now: established, listening sockets requires a way
more code change and we will do it only when really needed.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 criu/include/sockets.h |  2 ++
 criu/mount.c           |  7 +++++++
 criu/sk-unix.c         | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+)

diff --git a/criu/include/sockets.h b/criu/include/sockets.h
index 64673c5e5dc8..3d4669859182 100644
--- a/criu/include/sockets.h
+++ b/criu/include/sockets.h
@@ -8,6 +8,7 @@
 
 struct fdinfo_list_entry;
 struct sk_opts_entry;
+struct mount_info;
 struct file_desc;
 struct fd_parms;
 struct cr_imgset;
@@ -38,6 +39,7 @@ extern struct collect_image_info inet_sk_cinfo;
 extern struct collect_image_info unix_sk_cinfo;
 extern int fix_external_unix_sockets(void);
 extern int collect_unix_bindmounts(void);
+extern int unix_prepare_bindmount(struct mount_info *mi);
 
 extern struct collect_image_info netlink_sk_cinfo;
 
diff --git a/criu/mount.c b/criu/mount.c
index 59fd17870db8..174cc4639209 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -27,6 +27,7 @@
 #include "files-reg.h"
 #include "external.h"
 #include "fdstore.h"
+#include "sockets.h"
 
 #include "images/mnt.pb-c.h"
 
@@ -2042,6 +2043,12 @@ static int do_bind_mount(struct mount_info *mi)
 		}
 	}
 
+	if (unix_prepare_bindmount(mi)) {
+		pr_err("Failed to prepare bindmount on unix at %s\n",
+		       mi->mountpoint);
+		goto err;
+	}
+
 	if (mount(root, mi->mountpoint, NULL, MS_BIND | (mi->flags & MS_REC), NULL) < 0) {
 		pr_perror("Can't mount at %s", mi->mountpoint);
 		goto err;
diff --git a/criu/sk-unix.c b/criu/sk-unix.c
index bf013c5ca4de..adc6d58aa173 100644
--- a/criu/sk-unix.c
+++ b/criu/sk-unix.c
@@ -867,6 +867,7 @@ struct unix_sk_info {
 	struct file_desc d;
 	struct list_head connected; /* List of sockets, connected to me */
 	struct list_head node; /* To link in peer's connected list  */
+	int fdstore_id;
 
 	/*
 	 * For DGRAM sockets with queues, we should only restore the queue
@@ -1241,6 +1242,12 @@ static int open_unixsk_standalone(struct unix_sk_info *ui, int *new_fd)
 	pr_info("Opening standalone socket (id %#x ino %#x peer %#x)\n",
 			ui->ue->id, ui->ue->ino, ui->ue->peer);
 
+	if (ui->fdstore_id >= 0) {
+		pr_debug("\tObtaining from fdstore id %#x\n", ui->fdstore_id);
+		*new_fd = fdstore_get(ui->fdstore_id);
+		return 0;
+	}
+
 	if (set_netns(ui->ue->ns_id))
 		return -1;
 
@@ -1453,6 +1460,9 @@ static void unlink_stale(struct unix_sk_info *ui)
 {
 	int ret, cwd_fd = -1, root_fd = -1;
 
+	if (ui->fdstore_id >= 0)
+		return;
+
 	if (ui->name[0] == '\0' || (ui->ue->uflags & USK_EXTERN))
 		return;
 
@@ -1509,6 +1519,7 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base, struct cr_img *i)
 	INIT_LIST_HEAD(&ui->connected);
 	INIT_LIST_HEAD(&ui->node);
 	ui->flags = 0;
+	ui->fdstore_id = -1;
 	fixup_sock_net_ns_id(&ui->ue->ns_id, &ui->ue->has_ns_id);
 
 	uname = ui->name;
@@ -1553,6 +1564,48 @@ struct collect_image_info unix_sk_cinfo = {
 	.flags = COLLECT_SHARED,
 };
 
+int unix_prepare_bindmount(struct mount_info *mi)
+{
+	char name_dir[PATH_MAX], ns_root[PATH_MAX];
+	struct unix_sk_info *ui, *t = NULL;
+	char *old_name_dir = NULL;
+	int ret, sk;
+
+	list_for_each_entry(ui, &unix_sockets, list) {
+		if (!ui->ue->has_mnt_id || ui->ue->mnt_id != mi->mnt_id)
+			continue;
+		t = ui;
+		break;
+	}
+
+	if (!t)
+		return 0;
+
+	print_ns_root(mi->nsid, 0, ns_root, sizeof(ns_root));
+	if (ui->name_dir) {
+		old_name_dir = ui->name_dir;
+		snprintf(name_dir, sizeof(name_dir), "%s/%s", ns_root, ui->name_dir);
+		ui->name_dir = name_dir;
+	}
+
+	ret = open_unixsk_standalone(ui, &sk);
+	if (ui->name_dir)
+		ui->name_dir = old_name_dir;
+	BUG_ON(ret > 0);
+
+	if (ret)
+		return -1;
+
+	ui->fdstore_id = fdstore_add(sk);
+	if (ui->fdstore_id < 0)
+		return -1;
+	close(sk);
+
+	pr_debug("Standalone socket moved into fdstore (id %#x ino %#x peer %#x)\n",
+		 ui->ue->id, ui->ue->ino, ui->ue->peer);
+	return 0;
+}
+
 static void set_peer(struct unix_sk_info *ui, struct unix_sk_info *peer)
 {
 	ui->peer = peer;
-- 
2.7.5



More information about the CRIU mailing list