[01/10] uffdd: Implement --daemon mode

Submitted by Pavel Emelianov on Nov. 12, 2016, 5:23 a.m.

Details

Message ID 5826A750.6080700@virtuozzo.com
State Accepted
Series "uffd: A set of improvements over criu/uffd.c"
Commit 1daece63256ed40cd1b3f45336cbeffb62b6ff12
Headers show

Commit Message

Pavel Emelianov Nov. 12, 2016, 5:23 a.m.
Right now the zdtm.py hacks around core code and waits for
a second for the socket to appear. Let's better make proper
--daemon mode for lazy-pages daemon and pidfile generation.

Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
---
 criu/crtools.c         |  2 +-
 criu/include/crtools.h |  2 +-
 criu/uffd.c            | 47 ++++++++++++++++++++++++++++++++++++++++-------
 test/zdtm.py           | 12 +++---------
 4 files changed, 45 insertions(+), 18 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/crtools.c b/criu/crtools.c
index 72718cb..710059f 100644
--- a/criu/crtools.c
+++ b/criu/crtools.c
@@ -751,7 +751,7 @@  int main(int argc, char *argv[], char *envp[])
 	}
 
 	if (!strcmp(argv[optind], "lazy-pages"))
-		return cr_lazy_pages() != 0;
+		return cr_lazy_pages(opts.daemon_mode) != 0;
 
 	if (!strcmp(argv[optind], "check"))
 		return cr_check() != 0;
diff --git a/criu/include/crtools.h b/criu/include/crtools.h
index 0e26716..efd84ae 100644
--- a/criu/include/crtools.h
+++ b/criu/include/crtools.h
@@ -22,7 +22,7 @@  extern int convert_to_elf(char *elf_path, int fd_core);
 extern int cr_check(void);
 extern int cr_exec(int pid, char **opts);
 extern int cr_dedup(void);
-extern int cr_lazy_pages(void);
+extern int cr_lazy_pages(bool daemon);
 
 extern int check_add_feature(char *arg);
 extern void pr_check_features(const char *offset, const char *sep, int width);
diff --git a/criu/uffd.c b/criu/uffd.c
index 8d5e633..3472e7d 100644
--- a/criu/uffd.c
+++ b/criu/uffd.c
@@ -15,12 +15,13 @@ 
 #include <sys/un.h>
 #include <sys/socket.h>
 #include <sys/epoll.h>
+#include <sys/wait.h>
 
 #include "linux/userfaultfd.h"
 
 #include "int.h"
 #include "page.h"
-#include "log.h"
+#include "criu-log.h"
 #include "criu-plugin.h"
 #include "pagemap.h"
 #include "files-reg.h"
@@ -857,12 +858,9 @@  static int epoll_add_fd(int epollfd, int fd)
 	return 0;
 }
 
-static int prepare_uffds(int epollfd)
+static int prepare_lazy_socket(void)
 {
-	int i;
 	int listen;
-	int client;
-	socklen_t len;
 	struct sockaddr_un saddr;
 
 	if (prepare_sock_addr(&saddr))
@@ -874,6 +872,16 @@  static int prepare_uffds(int epollfd)
 		return -1;
 	}
 
+	return listen;
+}
+
+static int prepare_uffds(int listen, int epollfd)
+{
+	int i;
+	int client;
+	socklen_t len;
+	struct sockaddr_un saddr;
+
 	/* accept new client request */
 	len = sizeof(struct sockaddr_un);
 	if ((client = accept(listen, (struct sockaddr *) &saddr, &len)) < 0) {
@@ -904,10 +912,11 @@  close_uffd:
 	return -1;
 }
 
-int cr_lazy_pages()
+int cr_lazy_pages(bool daemon)
 {
 	struct epoll_event *events;
 	int epollfd;
+	int lazy_sk;
 	int ret;
 
 	if (check_for_uffd())
@@ -918,11 +927,35 @@  int cr_lazy_pages()
 	if (lazy_pages_prepare_pstree())
 		return -1;
 
+	lazy_sk = prepare_lazy_socket();
+	if (lazy_sk < 0)
+		return -1;
+
+	if (daemon) {
+		ret = cr_daemon(1, 0, &lazy_sk, -1);
+		if (ret == -1) {
+			pr_err("Can't run in the background\n");
+			return -1;
+		}
+		if (ret > 0) { /* parent task, daemon started */
+			if (opts.pidfile) {
+				if (write_pidfile(ret) == -1) {
+					pr_perror("Can't write pidfile");
+					kill(ret, SIGKILL);
+					waitpid(ret, NULL, 0);
+					return -1;
+				}
+			}
+
+			return 0;
+		}
+	}
+
 	epollfd = prepare_epoll(task_entries->nr_tasks, &events);
 	if (epollfd < 0)
 		return -1;
 
-	if (prepare_uffds(epollfd))
+	if (prepare_uffds(lazy_sk, epollfd))
 		return -1;
 
 	if (connect_to_page_server())
diff --git a/test/zdtm.py b/test/zdtm.py
index 0d8503f..3bd9010 100755
--- a/test/zdtm.py
+++ b/test/zdtm.py
@@ -679,8 +679,6 @@  class criu_cli:
 			print "Forcing %s fault" % fault
 			env = dict(os.environ, CRIU_FAULT = fault)
 		cr = subprocess.Popen(strace + [criu_bin, action] + args, env = env, preexec_fn = preexec)
-		if action == "lazy-pages":
-			return cr
 		return cr.wait()
 
 
@@ -839,8 +837,6 @@  class criu:
 		__ddir = self.__ddir()
 
 		ret = self.__criu.run(action, s_args, self.__fault, strace, preexec)
-		if action == "lazy-pages":
-			return ret
 
 		grep_errors(os.path.join(__ddir, log))
 		if ret != 0:
@@ -927,11 +923,9 @@  class criu:
 			r_opts.append('--external')
 			r_opts.append('mnt[zdtm]:%s' % criu_dir)
 
-		lazy_pages_p = None
 		if self.__lazy_pages:
-			lazy_pages_p = self.__criu_act("lazy-pages", opts = [])
+			self.__criu_act("lazy-pages", opts = ["--daemon", "--pidfile", "lp.pid"])
 			r_opts += ["--lazy-pages"]
-			time.sleep(1)  # FIXME wait user fault fd socket
 
 		if self.__leave_stopped:
 			r_opts += ['--leave-stopped']
@@ -942,8 +936,8 @@  class criu:
 			pstree_check_stopped(self.__test.getpid())
 			pstree_signal(self.__test.getpid(), signal.SIGCONT)
 
-		if lazy_pages_p and lazy_pages_p.wait():
-			raise test_fail_exc("CRIU lazy-pages")
+		if self.__lazy_pages:
+			wait_pid_die(int(rpidfile(self.__ddir() + "/lp.pid")), "lazy pages daemon")
 
 	@staticmethod
 	def check(feature):

Comments

Mike Rapoport Nov. 12, 2016, 1:39 p.m.
On Sat, Nov 12, 2016 at 08:23:28AM +0300, Pavel Emelyanov wrote:
> Right now the zdtm.py hacks around core code and waits for
> a second for the socket to appear. Let's better make proper
> --daemon mode for lazy-pages daemon and pidfile generation.
> 
> Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
> ---
>  criu/crtools.c         |  2 +-
>  criu/include/crtools.h |  2 +-
>  criu/uffd.c            | 47 ++++++++++++++++++++++++++++++++++++++++-------
>  test/zdtm.py           | 12 +++---------
>  4 files changed, 45 insertions(+), 18 deletions(-)
> 
> diff --git a/criu/crtools.c b/criu/crtools.c
> index 72718cb..710059f 100644
> --- a/criu/crtools.c
> +++ b/criu/crtools.c
> @@ -751,7 +751,7 @@ int main(int argc, char *argv[], char *envp[])
>  	}
> 
>  	if (!strcmp(argv[optind], "lazy-pages"))
> -		return cr_lazy_pages() != 0;
> +		return cr_lazy_pages(opts.daemon_mode) != 0;
> 
>  	if (!strcmp(argv[optind], "check"))
>  		return cr_check() != 0;
> diff --git a/criu/include/crtools.h b/criu/include/crtools.h
> index 0e26716..efd84ae 100644
> --- a/criu/include/crtools.h
> +++ b/criu/include/crtools.h
> @@ -22,7 +22,7 @@ extern int convert_to_elf(char *elf_path, int fd_core);
>  extern int cr_check(void);
>  extern int cr_exec(int pid, char **opts);
>  extern int cr_dedup(void);
> -extern int cr_lazy_pages(void);
> +extern int cr_lazy_pages(bool daemon);
> 
>  extern int check_add_feature(char *arg);
>  extern void pr_check_features(const char *offset, const char *sep, int width);
> diff --git a/criu/uffd.c b/criu/uffd.c
> index 8d5e633..3472e7d 100644
> --- a/criu/uffd.c
> +++ b/criu/uffd.c
> @@ -15,12 +15,13 @@
>  #include <sys/un.h>
>  #include <sys/socket.h>
>  #include <sys/epoll.h>
> +#include <sys/wait.h>
> 
>  #include "linux/userfaultfd.h"
> 
>  #include "int.h"
>  #include "page.h"
> -#include "log.h"
> +#include "criu-log.h"
>  #include "criu-plugin.h"
>  #include "pagemap.h"
>  #include "files-reg.h"
> @@ -857,12 +858,9 @@ static int epoll_add_fd(int epollfd, int fd)
>  	return 0;
>  }
> 
> -static int prepare_uffds(int epollfd)
> +static int prepare_lazy_socket(void)
>  {
> -	int i;
>  	int listen;
> -	int client;
> -	socklen_t len;
>  	struct sockaddr_un saddr;
> 
>  	if (prepare_sock_addr(&saddr))
> @@ -874,6 +872,16 @@ static int prepare_uffds(int epollfd)
>  		return -1;
>  	}
> 
> +	return listen;
> +}
> +
> +static int prepare_uffds(int listen, int epollfd)
> +{
> +	int i;
> +	int client;
> +	socklen_t len;
> +	struct sockaddr_un saddr;
> +
>  	/* accept new client request */
>  	len = sizeof(struct sockaddr_un);
>  	if ((client = accept(listen, (struct sockaddr *) &saddr, &len)) < 0) {
> @@ -904,10 +912,11 @@ close_uffd:
>  	return -1;
>  }
> 
> -int cr_lazy_pages()
> +int cr_lazy_pages(bool daemon)
>  {
>  	struct epoll_event *events;
>  	int epollfd;
> +	int lazy_sk;
>  	int ret;
> 
>  	if (check_for_uffd())
> @@ -918,11 +927,35 @@ int cr_lazy_pages()
>  	if (lazy_pages_prepare_pstree())
>  		return -1;
> 
> +	lazy_sk = prepare_lazy_socket();
> +	if (lazy_sk < 0)
> +		return -1;
> +
> +	if (daemon) {
> +		ret = cr_daemon(1, 0, &lazy_sk, -1);
> +		if (ret == -1) {
> +			pr_err("Can't run in the background\n");
> +			return -1;
> +		}
> +		if (ret > 0) { /* parent task, daemon started */
> +			if (opts.pidfile) {
> +				if (write_pidfile(ret) == -1) {
> +					pr_perror("Can't write pidfile");
> +					kill(ret, SIGKILL);
> +					waitpid(ret, NULL, 0);
> +					return -1;
> +				}
> +			}

This seems pretty much a copy from run_tcp_server. Maybe we'll move pidfile
creation into cr_daemon?

> +
> +			return 0;
> +		}
> +	}
> +
>  	epollfd = prepare_epoll(task_entries->nr_tasks, &events);
>  	if (epollfd < 0)
>  		return -1;
> 
> -	if (prepare_uffds(epollfd))
> +	if (prepare_uffds(lazy_sk, epollfd))
>  		return -1;
> 
>  	if (connect_to_page_server())
> diff --git a/test/zdtm.py b/test/zdtm.py
> index 0d8503f..3bd9010 100755
> --- a/test/zdtm.py
> +++ b/test/zdtm.py
> @@ -679,8 +679,6 @@ class criu_cli:
>  			print "Forcing %s fault" % fault
>  			env = dict(os.environ, CRIU_FAULT = fault)
>  		cr = subprocess.Popen(strace + [criu_bin, action] + args, env = env, preexec_fn = preexec)
> -		if action == "lazy-pages":
> -			return cr
>  		return cr.wait()
> 
> 
> @@ -839,8 +837,6 @@ class criu:
>  		__ddir = self.__ddir()
> 
>  		ret = self.__criu.run(action, s_args, self.__fault, strace, preexec)
> -		if action == "lazy-pages":
> -			return ret
> 
>  		grep_errors(os.path.join(__ddir, log))
>  		if ret != 0:
> @@ -927,11 +923,9 @@ class criu:
>  			r_opts.append('--external')
>  			r_opts.append('mnt[zdtm]:%s' % criu_dir)
> 
> -		lazy_pages_p = None
>  		if self.__lazy_pages:
> -			lazy_pages_p = self.__criu_act("lazy-pages", opts = [])
> +			self.__criu_act("lazy-pages", opts = ["--daemon", "--pidfile", "lp.pid"])
>  			r_opts += ["--lazy-pages"]
> -			time.sleep(1)  # FIXME wait user fault fd socket
> 
>  		if self.__leave_stopped:
>  			r_opts += ['--leave-stopped']
> @@ -942,8 +936,8 @@ class criu:
>  			pstree_check_stopped(self.__test.getpid())
>  			pstree_signal(self.__test.getpid(), signal.SIGCONT)
> 
> -		if lazy_pages_p and lazy_pages_p.wait():
> -			raise test_fail_exc("CRIU lazy-pages")
> +		if self.__lazy_pages:
> +			wait_pid_die(int(rpidfile(self.__ddir() + "/lp.pid")), "lazy pages daemon")
> 
>  	@staticmethod
>  	def check(feature):
> -- 
> 2.5.0
> 
> _______________________________________________
> CRIU mailing list
> CRIU@openvz.org
> https://lists.openvz.org/mailman/listinfo/criu
>