[CRIU] [PATCH 1/2] criu: lazy-pages: refactor UNIX socket initialization

Mike Rapoport rppt at linux.vnet.ibm.com
Mon Aug 15 00:21:50 PDT 2016


Create the socket early so that it will be available after restoring the
namespaces

Signed-off-by: Mike Rapoport <rppt at linux.vnet.ibm.com>
---
 criu/cr-restore.c        |  3 ++
 criu/include/servicefd.h |  1 +
 criu/include/uffd.h      |  1 +
 criu/uffd.c              | 90 +++++++++++++++++++++++++++++++++---------------
 4 files changed, 68 insertions(+), 27 deletions(-)

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index b0ed609..06dcfa5 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -2078,6 +2078,9 @@ int cr_restore_tasks(void)
 	if (criu_signals_setup() < 0)
 		goto err;
 
+	if (prepare_lazy_pages_socket() < 0)
+		goto err;
+
 	ret = restore_root_task(root_item);
 err:
 	cr_plugin_fini(CR_PLUGIN_STAGE__RESTORE, ret);
diff --git a/criu/include/servicefd.h b/criu/include/servicefd.h
index a35f25a..5152fb6 100644
--- a/criu/include/servicefd.h
+++ b/criu/include/servicefd.h
@@ -20,6 +20,7 @@ enum sfd_type {
 	USERNSD_SK,	/* Socket for usernsd */
 	NS_FD_OFF,	/* Node's net namespace fd */
 	TRANSPORT_FD_OFF, /* to transfer file descriptors */
+	LAZY_PAGES_SK_OFF, /* socket for communication with lazy-pages daemon */
 
 	SERVICE_FD_MAX
 };
diff --git a/criu/include/uffd.h b/criu/include/uffd.h
index 66ce459..d8cf0d0 100644
--- a/criu/include/uffd.h
+++ b/criu/include/uffd.h
@@ -3,5 +3,6 @@
 
 struct task_restore_args;
 extern int setup_uffd(int pid, struct task_restore_args *task_args);
+extern int prepare_lazy_pages_socket(void);
 
 #endif /* __CR_UFFD_H_ */
diff --git a/criu/uffd.c b/criu/uffd.c
index aecc042..cf03c31 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -35,12 +35,16 @@
 #include "syscall-codes.h"
 #include "restorer.h"
 #include "page-xfer.h"
+#include "lock.h"
+#include "rst-malloc.h"
 
 #undef  LOG_PREFIX
 #define LOG_PREFIX "lazy-pages: "
 
 #define LAZY_PAGES_SOCK_NAME	"lazy-pages.socket"
 
+static mutex_t *lazy_sock_mutex;
+
 struct lazy_pages_info {
 	int pid;
 	int uffd;
@@ -145,25 +149,19 @@ static int prepare_sock_addr(struct sockaddr_un *saddr)
 static int send_uffd(int sendfd, int pid)
 {
 	int fd;
-	int len;
 	int ret = -1;
-	struct sockaddr_un sun;
 
 	if (sendfd < 0)
 		return -1;
 
-	if (prepare_sock_addr(&sun))
+	fd = get_service_fd(LAZY_PAGES_SK_OFF);
+	if (fd < 0) {
+		pr_err("%s: get_service_fd\n", __func__);
 		return -1;
-
-	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
-		return -1;
-
-	len = offsetof(struct sockaddr_un, sun_path) + strlen(sun.sun_path);
-	if (connect(fd, (struct sockaddr *) &sun, len) < 0) {
-		pr_perror("connect to %s failed", sun.sun_path);
-		goto out;
 	}
 
+	mutex_lock(lazy_sock_mutex);
+
 	/* The "transfer protocol" is first the pid as int and then
 	 * the FD for UFFD */
 	pr_debug("Sending PID %d\n", pid);
@@ -176,6 +174,9 @@ static int send_uffd(int sendfd, int pid)
 		pr_perror("send_fd error:");
 		goto out;
 	}
+
+	mutex_unlock(lazy_sock_mutex);
+
 	ret = 0;
 out:
 	close(fd);
@@ -248,6 +249,42 @@ err:
 	return -1;
 }
 
+int prepare_lazy_pages_socket(void)
+{
+	int fd, new_fd;
+	int len;
+	struct sockaddr_un sun;
+
+	if (!opts.lazy_pages)
+		return 0;
+
+	if (prepare_sock_addr(&sun))
+		return -1;
+
+	lazy_sock_mutex = shmalloc(sizeof(*lazy_sock_mutex));
+	if (!lazy_sock_mutex)
+		return -1;
+
+	mutex_init(lazy_sock_mutex);
+
+	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+		return -1;
+
+	new_fd = install_service_fd(LAZY_PAGES_SK_OFF, fd);
+	close(fd);
+	if (new_fd < 0)
+		return -1;
+
+	len = offsetof(struct sockaddr_un, sun_path) + strlen(sun.sun_path);
+	if (connect(new_fd, (struct sockaddr *) &sun, len) < 0) {
+		pr_perror("connect to %s failed", sun.sun_path);
+		close(new_fd);
+		return -1;
+	}
+
+	return 0;
+}
+
 static int server_listen(struct sockaddr_un *saddr)
 {
 	int fd;
@@ -277,24 +314,12 @@ out:
 
 static int find_vmas(struct lazy_pages_info *lpi);
 
-static struct lazy_pages_info *ud_open(int listen, struct sockaddr_un *saddr)
+static struct lazy_pages_info *ud_open(int client)
 {
 	struct lazy_pages_info *lpi;
-	int client;
 	int ret = -1;
-	socklen_t len;
 	int uffd_flags;
 
-	/* accept new client request */
-	len = sizeof(struct sockaddr_un);
-	if ((client = accept(listen, (struct sockaddr *) saddr, &len)) < 0) {
-		pr_perror("server_accept error: %d", client);
-		close(listen);
-		return NULL;
-	}
-
-	pr_debug("client fd %d\n", client);
-
 	lpi = lpi_init();
 	if (!lpi)
 		goto out;
@@ -314,7 +339,6 @@ static struct lazy_pages_info *ud_open(int listen, struct sockaddr_un *saddr)
 		goto out;
 	}
 	pr_debug("lpi->uffd %d\n", lpi->uffd);
-	close_safe(&client);
 
 	pr_debug("uffd is 0x%d\n", lpi->uffd);
 	uffd_flags = fcntl(lpi->uffd, F_GETFD, NULL);
@@ -333,7 +357,6 @@ static struct lazy_pages_info *ud_open(int listen, struct sockaddr_un *saddr)
 
 out:
 	lpi_fini(lpi);
-	close_safe(&client);
 	return NULL;
 }
 
@@ -817,6 +840,8 @@ static int prepare_uffds(int epollfd)
 {
 	int i;
 	int listen;
+	int client;
+	socklen_t len;
 	struct sockaddr_un saddr;
 
 	if (prepare_sock_addr(&saddr))
@@ -828,20 +853,31 @@ static int prepare_uffds(int epollfd)
 		return -1;
 	}
 
+	/* accept new client request */
+	len = sizeof(struct sockaddr_un);
+	if ((client = accept(listen, (struct sockaddr *) &saddr, &len)) < 0) {
+		pr_perror("server_accept error: %d", client);
+		close(listen);
+		return -1;
+	}
+	pr_debug("client fd %d\n", client);
+
 	for (i = 0; i < task_entries->nr_tasks; i++) {
 		struct lazy_pages_info *lpi;
-		lpi = ud_open(listen, &saddr);
+		lpi = ud_open(client);
 		if (!lpi)
 			goto close_uffd;
 		if (epoll_add_fd(epollfd, lpi->uffd))
 			goto close_uffd;
 	}
 
+	close_safe(&client);
 	close(listen);
 	return 0;
 
 close_uffd:
 	lpi_hash_fini();
+	close_safe(&client);
 	close(listen);
 	return -1;
 }
-- 
1.9.1



More information about the CRIU mailing list