[CRIU] [PATCH 1/2] tests: move non-zdtm tests to tests/others/

Andrey Vagin avagin at openvz.org
Fri Feb 19 13:11:39 PST 2016


From: Andrew Vagin <avagin at virtuozzo.com>

Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 scripts/build/extract-deb-pkg                     |   4 +-
 test/bers/Makefile                                |  47 --
 test/bers/bers.c                                  | 420 -------------
 test/bers/bers.txt                                |  74 ---
 test/ext-links/Makefile                           |   4 -
 test/ext-links/addmv.sh                           |   8 -
 test/ext-links/addmv_raw.sh                       |   6 -
 test/ext-links/mvlink.c                           |  28 -
 test/ext-links/run.sh                             |  58 --
 test/ext-links/run_ns.sh                          |  10 -
 test/ext-links/run_wait.sh                        |  15 -
 test/ext-tty/run.py                               |  36 --
 test/fault-injection/Makefile                     |   2 -
 test/fault-injection/parasite.stp                 |  44 --
 test/libcriu/.gitignore                           |   6 -
 test/libcriu/Makefile                             |  26 -
 test/libcriu/lib.c                                |  47 --
 test/libcriu/lib.h                                |   2 -
 test/libcriu/run.sh                               |  44 --
 test/libcriu/test_errno.c                         | 154 -----
 test/libcriu/test_iters.c                         | 143 -----
 test/libcriu/test_notify.c                        |  97 ---
 test/libcriu/test_self.c                          |  96 ---
 test/libcriu/test_sub.c                           | 107 ----
 test/mem-snap/Makefile                            |   2 -
 test/mem-snap/run-predump-2.sh                    |  66 ---
 test/mem-snap/run-predump.sh                      |  77 ---
 test/mem-snap/run-snap-auto-dedup.sh              |  93 ---
 test/mem-snap/run-snap-dedup-on-restore.sh        |  87 ---
 test/mem-snap/run-snap-dedup.sh                   |  99 ----
 test/mem-snap/run-snap-maps04.sh                  |  68 ---
 test/mem-snap/run-snap.sh                         |  74 ---
 test/mem-snap/run.sh                              |  13 -
 test/mounts/ext/Makefile                          |  13 -
 test/mounts/ext/ext-mount.c                       | 101 ----
 test/mounts/ext/ns_init.c                         | 143 -----
 test/mounts/ext/run.sh                            | 125 ----
 test/mounts/mounts.py                             |  31 -
 test/mounts/mounts.sh                             |  27 -
 test/mounts/run.sh                                |  24 -
 test/others/bers/Makefile                         |  47 ++
 test/others/bers/bers.c                           | 420 +++++++++++++
 test/others/bers/bers.txt                         |  74 +++
 test/others/ext-links/Makefile                    |   4 +
 test/others/ext-links/addmv.sh                    |   8 +
 test/others/ext-links/addmv_raw.sh                |   6 +
 test/others/ext-links/mvlink.c                    |  28 +
 test/others/ext-links/run.sh                      |  58 ++
 test/others/ext-links/run_ns.sh                   |  10 +
 test/others/ext-links/run_wait.sh                 |  15 +
 test/others/ext-tty/run.py                        |  36 ++
 test/others/fault-injection/Makefile              |   2 +
 test/others/fault-injection/parasite.stp          |  44 ++
 test/others/libcriu/.gitignore                    |   6 +
 test/others/libcriu/Makefile                      |  26 +
 test/others/libcriu/lib.c                         |  47 ++
 test/others/libcriu/lib.h                         |   2 +
 test/others/libcriu/run.sh                        |  45 ++
 test/others/libcriu/test_errno.c                  | 154 +++++
 test/others/libcriu/test_iters.c                  | 143 +++++
 test/others/libcriu/test_notify.c                 |  97 +++
 test/others/libcriu/test_self.c                   |  96 +++
 test/others/libcriu/test_sub.c                    | 107 ++++
 test/others/mem-snap/Makefile                     |   2 +
 test/others/mem-snap/run-predump-2.sh             |  66 +++
 test/others/mem-snap/run-predump.sh               |  77 +++
 test/others/mem-snap/run-snap-auto-dedup.sh       |  93 +++
 test/others/mem-snap/run-snap-dedup-on-restore.sh |  87 +++
 test/others/mem-snap/run-snap-dedup.sh            |  99 ++++
 test/others/mem-snap/run-snap-maps04.sh           |  68 +++
 test/others/mem-snap/run-snap.sh                  |  74 +++
 test/others/mem-snap/run.sh                       |  13 +
 test/others/mounts/ext/Makefile                   |  13 +
 test/others/mounts/ext/ext-mount.c                | 101 ++++
 test/others/mounts/ext/ns_init.c                  | 143 +++++
 test/others/mounts/ext/run.sh                     | 125 ++++
 test/others/mounts/mounts.py                      |  31 +
 test/others/mounts/mounts.sh                      |  27 +
 test/others/mounts/run.sh                         |  24 +
 test/others/overlayfs/Makefile                    |   6 +
 test/others/overlayfs/run.sh                      |  58 ++
 test/others/pipes/Makefile                        |  14 +
 test/others/pipes/pipe.c                          | 693 ++++++++++++++++++++++
 test/others/rpc/.gitignore                        |   3 +
 test/others/rpc/Makefile                          |  28 +
 test/others/rpc/errno.py                          | 135 +++++
 test/others/rpc/loop.sh                           |   4 +
 test/others/rpc/ps_test.py                        |  73 +++
 test/others/rpc/restore-loop.py                   |  40 ++
 test/others/rpc/rpc.proto                         |   1 +
 test/others/rpc/run.sh                            |  91 +++
 test/others/rpc/test-c.c                          | 170 ++++++
 test/others/rpc/test.py                           |  44 ++
 test/others/security/Makefile                     |  34 ++
 test/others/security/loop.sh                      |  13 +
 test/others/security/run.sh                       |  89 +++
 test/others/socketpairs/Makefile                  |   9 +
 test/others/socketpairs/socketpair.c              | 600 +++++++++++++++++++
 test/others/tcp/Makefile                          |  11 +
 test/others/tcp/cln.c                             | 122 ++++
 test/others/tcp/run.sh                            |  67 +++
 test/others/tcp/srv.c                             | 112 ++++
 test/others/unix-callback/Makefile                |  22 +
 test/others/unix-callback/lib/syslog-lib.so       |   1 +
 test/others/unix-callback/lib/unix-lib.so         |   1 +
 test/others/unix-callback/run.sh                  |  48 ++
 test/others/unix-callback/syslog-lib.c            |  66 +++
 test/others/unix-callback/unix-client.c           | 121 ++++
 test/others/unix-callback/unix-lib.c              | 187 ++++++
 test/others/unix-callback/unix-server.c           | 104 ++++
 test/others/unix-callback/unix.proto              |   4 +
 test/overlayfs/Makefile                           |   6 -
 test/overlayfs/run.sh                             |  58 --
 test/pipes/Makefile                               |  14 -
 test/pipes/pipe.c                                 | 693 ----------------------
 test/rpc/.gitignore                               |   3 -
 test/rpc/Makefile                                 |  28 -
 test/rpc/errno.py                                 | 135 -----
 test/rpc/loop.sh                                  |   4 -
 test/rpc/ps_test.py                               |  73 ---
 test/rpc/restore-loop.py                          |  40 --
 test/rpc/rpc.proto                                |   1 -
 test/rpc/run.sh                                   |  91 ---
 test/rpc/test-c.c                                 | 170 ------
 test/rpc/test.py                                  |  44 --
 test/security/Makefile                            |  34 --
 test/security/loop.sh                             |  13 -
 test/security/run.sh                              |  89 ---
 test/socketpairs/Makefile                         |   9 -
 test/socketpairs/socketpair.c                     | 600 -------------------
 test/tcp/Makefile                                 |  11 -
 test/tcp/cln.c                                    | 122 ----
 test/tcp/run.sh                                   |  67 ---
 test/tcp/srv.c                                    | 112 ----
 test/unix-callback/Makefile                       |  22 -
 test/unix-callback/lib/syslog-lib.so              |   1 -
 test/unix-callback/lib/unix-lib.so                |   1 -
 test/unix-callback/run.sh                         |  48 --
 test/unix-callback/syslog-lib.c                   |  66 ---
 test/unix-callback/unix-client.c                  | 121 ----
 test/unix-callback/unix-lib.c                     | 187 ------
 test/unix-callback/unix-server.c                  | 104 ----
 test/unix-callback/unix.proto                     |   4 -
 143 files changed, 5491 insertions(+), 5490 deletions(-)
 delete mode 100644 test/bers/Makefile
 delete mode 100644 test/bers/bers.c
 delete mode 100644 test/bers/bers.txt
 delete mode 100644 test/ext-links/Makefile
 delete mode 100755 test/ext-links/addmv.sh
 delete mode 100755 test/ext-links/addmv_raw.sh
 delete mode 100644 test/ext-links/mvlink.c
 delete mode 100755 test/ext-links/run.sh
 delete mode 100755 test/ext-links/run_ns.sh
 delete mode 100755 test/ext-links/run_wait.sh
 delete mode 100755 test/ext-tty/run.py
 delete mode 100644 test/fault-injection/Makefile
 delete mode 100644 test/fault-injection/parasite.stp
 delete mode 100644 test/libcriu/.gitignore
 delete mode 100644 test/libcriu/Makefile
 delete mode 100644 test/libcriu/lib.c
 delete mode 100644 test/libcriu/lib.h
 delete mode 100755 test/libcriu/run.sh
 delete mode 100644 test/libcriu/test_errno.c
 delete mode 100644 test/libcriu/test_iters.c
 delete mode 100644 test/libcriu/test_notify.c
 delete mode 100644 test/libcriu/test_self.c
 delete mode 100644 test/libcriu/test_sub.c
 delete mode 100644 test/mem-snap/Makefile
 delete mode 100755 test/mem-snap/run-predump-2.sh
 delete mode 100755 test/mem-snap/run-predump.sh
 delete mode 100755 test/mem-snap/run-snap-auto-dedup.sh
 delete mode 100755 test/mem-snap/run-snap-dedup-on-restore.sh
 delete mode 100755 test/mem-snap/run-snap-dedup.sh
 delete mode 100755 test/mem-snap/run-snap-maps04.sh
 delete mode 100755 test/mem-snap/run-snap.sh
 delete mode 100755 test/mem-snap/run.sh
 delete mode 100644 test/mounts/ext/Makefile
 delete mode 100644 test/mounts/ext/ext-mount.c
 delete mode 100644 test/mounts/ext/ns_init.c
 delete mode 100755 test/mounts/ext/run.sh
 delete mode 100755 test/mounts/mounts.py
 delete mode 100755 test/mounts/mounts.sh
 delete mode 100755 test/mounts/run.sh
 create mode 100644 test/others/bers/Makefile
 create mode 100644 test/others/bers/bers.c
 create mode 100644 test/others/bers/bers.txt
 create mode 100644 test/others/ext-links/Makefile
 create mode 100755 test/others/ext-links/addmv.sh
 create mode 100755 test/others/ext-links/addmv_raw.sh
 create mode 100644 test/others/ext-links/mvlink.c
 create mode 100755 test/others/ext-links/run.sh
 create mode 100755 test/others/ext-links/run_ns.sh
 create mode 100755 test/others/ext-links/run_wait.sh
 create mode 100755 test/others/ext-tty/run.py
 create mode 100644 test/others/fault-injection/Makefile
 create mode 100644 test/others/fault-injection/parasite.stp
 create mode 100644 test/others/libcriu/.gitignore
 create mode 100644 test/others/libcriu/Makefile
 create mode 100644 test/others/libcriu/lib.c
 create mode 100644 test/others/libcriu/lib.h
 create mode 100755 test/others/libcriu/run.sh
 create mode 100644 test/others/libcriu/test_errno.c
 create mode 100644 test/others/libcriu/test_iters.c
 create mode 100644 test/others/libcriu/test_notify.c
 create mode 100644 test/others/libcriu/test_self.c
 create mode 100644 test/others/libcriu/test_sub.c
 create mode 100644 test/others/mem-snap/Makefile
 create mode 100755 test/others/mem-snap/run-predump-2.sh
 create mode 100755 test/others/mem-snap/run-predump.sh
 create mode 100755 test/others/mem-snap/run-snap-auto-dedup.sh
 create mode 100755 test/others/mem-snap/run-snap-dedup-on-restore.sh
 create mode 100755 test/others/mem-snap/run-snap-dedup.sh
 create mode 100755 test/others/mem-snap/run-snap-maps04.sh
 create mode 100755 test/others/mem-snap/run-snap.sh
 create mode 100755 test/others/mem-snap/run.sh
 create mode 100644 test/others/mounts/ext/Makefile
 create mode 100644 test/others/mounts/ext/ext-mount.c
 create mode 100644 test/others/mounts/ext/ns_init.c
 create mode 100755 test/others/mounts/ext/run.sh
 create mode 100755 test/others/mounts/mounts.py
 create mode 100755 test/others/mounts/mounts.sh
 create mode 100755 test/others/mounts/run.sh
 create mode 100644 test/others/overlayfs/Makefile
 create mode 100755 test/others/overlayfs/run.sh
 create mode 100644 test/others/pipes/Makefile
 create mode 100644 test/others/pipes/pipe.c
 create mode 100644 test/others/rpc/.gitignore
 create mode 100644 test/others/rpc/Makefile
 create mode 100755 test/others/rpc/errno.py
 create mode 100755 test/others/rpc/loop.sh
 create mode 100755 test/others/rpc/ps_test.py
 create mode 100755 test/others/rpc/restore-loop.py
 create mode 120000 test/others/rpc/rpc.proto
 create mode 100755 test/others/rpc/run.sh
 create mode 100644 test/others/rpc/test-c.c
 create mode 100755 test/others/rpc/test.py
 create mode 100644 test/others/security/Makefile
 create mode 100755 test/others/security/loop.sh
 create mode 100755 test/others/security/run.sh
 create mode 100644 test/others/socketpairs/Makefile
 create mode 100644 test/others/socketpairs/socketpair.c
 create mode 100644 test/others/tcp/Makefile
 create mode 100644 test/others/tcp/cln.c
 create mode 100755 test/others/tcp/run.sh
 create mode 100644 test/others/tcp/srv.c
 create mode 100644 test/others/unix-callback/Makefile
 create mode 120000 test/others/unix-callback/lib/syslog-lib.so
 create mode 120000 test/others/unix-callback/lib/unix-lib.so
 create mode 100755 test/others/unix-callback/run.sh
 create mode 100644 test/others/unix-callback/syslog-lib.c
 create mode 100644 test/others/unix-callback/unix-client.c
 create mode 100644 test/others/unix-callback/unix-lib.c
 create mode 100644 test/others/unix-callback/unix-server.c
 create mode 100644 test/others/unix-callback/unix.proto
 delete mode 100644 test/overlayfs/Makefile
 delete mode 100755 test/overlayfs/run.sh
 delete mode 100644 test/pipes/Makefile
 delete mode 100644 test/pipes/pipe.c
 delete mode 100644 test/rpc/.gitignore
 delete mode 100644 test/rpc/Makefile
 delete mode 100755 test/rpc/errno.py
 delete mode 100755 test/rpc/loop.sh
 delete mode 100755 test/rpc/ps_test.py
 delete mode 100755 test/rpc/restore-loop.py
 delete mode 120000 test/rpc/rpc.proto
 delete mode 100755 test/rpc/run.sh
 delete mode 100644 test/rpc/test-c.c
 delete mode 100755 test/rpc/test.py
 delete mode 100644 test/security/Makefile
 delete mode 100755 test/security/loop.sh
 delete mode 100755 test/security/run.sh
 delete mode 100644 test/socketpairs/Makefile
 delete mode 100644 test/socketpairs/socketpair.c
 delete mode 100644 test/tcp/Makefile
 delete mode 100644 test/tcp/cln.c
 delete mode 100755 test/tcp/run.sh
 delete mode 100644 test/tcp/srv.c
 delete mode 100644 test/unix-callback/Makefile
 delete mode 120000 test/unix-callback/lib/syslog-lib.so
 delete mode 120000 test/unix-callback/lib/unix-lib.so
 delete mode 100755 test/unix-callback/run.sh
 delete mode 100644 test/unix-callback/syslog-lib.c
 delete mode 100644 test/unix-callback/unix-client.c
 delete mode 100644 test/unix-callback/unix-lib.c
 delete mode 100644 test/unix-callback/unix-server.c
 delete mode 100644 test/unix-callback/unix.proto

diff --git a/scripts/build/extract-deb-pkg b/scripts/build/extract-deb-pkg
index 8ccec37..ac63319 100755
--- a/scripts/build/extract-deb-pkg
+++ b/scripts/build/extract-deb-pkg
@@ -3,8 +3,8 @@ set -e
 test -d $1 && exit
 mkdir $1
 cd $1
-pkg=`curl http://mirror.yandex.ru/debian/dists/jessie/main/binary-amd64/Packages.gz | zcat | grep "Filename.*$1" | awk '{ print $2 }'`
-wget "http://mirror.yandex.ru/debian/$pkg"
+pkg=`curl http://mirror.yandex.ru/ubuntu/ubuntu/dists/wily/universe/binary-amd64/Packages.gz | zcat | grep "Filename.*$1" | awk '{ print $2 }'`
+wget "http://mirror.yandex.ru/ubuntu/$pkg"
 pkg=`basename $pkg`
 ar vx $pkg
 tar -xJvf data.tar.xz
diff --git a/test/bers/Makefile b/test/bers/Makefile
deleted file mode 100644
index 74b6142..0000000
--- a/test/bers/Makefile
+++ /dev/null
@@ -1,47 +0,0 @@
-ifeq ($(strip $(V)),)
-	E = @echo
-	Q = @
-else
-	E = @\#
-	Q =
-endif
-
-export E Q
-
-ASCIIDOC	:= asciidoc
-A2X		:= a2x
-XMLTO		:= xmlto
-
-SRC		+= bers.txt
-XMLS		:= $(patsubst %.txt,%.xml,$(SRC))
-MANS		:= $(patsubst %.txt,%.8,$(SRC))
-
-%.8: %.txt
-	$(E) "  GEN     " $@
-	$(Q) $(ASCIIDOC) -b docbook -d manpage -o $(patsubst %.8,%.xml,$@) $<
-	$(Q) $(XMLTO) man --skip-validation $(patsubst %.8,%.xml,$@) 2>/dev/null
-
-docs: $(MANS)
-	@true
-
-CFLAGS := -O0 -ggdb3
-LIBS := -lpthread
-
-%.o: %.c
-	$(E) "  CC      " $@
-	$(Q) $(CC) -c -o $@ $(CFLAGS) $^
-
-bers: bers.o
-	$(E) "  LINK    " $@
-	$(Q) $(CC) -o $@ $(CFLAGS) $(LIBS) $^
-
-all: bers
-	@true
-
-clean:
-	$(E) "  CLEAN   "
-	$(Q) rm -f $(XMLS) $(MANS)
-	$(Q) rm -f bers.o
-	$(Q) rm -f bers
-
-.PHONY: all docs clean
diff --git a/test/bers/bers.c b/test/bers/bers.c
deleted file mode 100644
index 208325c..0000000
--- a/test/bers/bers.c
+++ /dev/null
@@ -1,420 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <string.h>
-#include <limits.h>
-#include <stdbool.h>
-
-#include <pthread.h>
-#include <sys/mman.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <syscall.h>
-
-#define min(x, y) ({				\
-	typeof(x) _min1 = (x);			\
-	typeof(y) _min2 = (y);			\
-	(void) (&_min1 == &_min2);		\
-	_min1 < _min2 ? _min1 : _min2; })
-
-#define max(x, y) ({				\
-	typeof(x) _max1 = (x);			\
-	typeof(y) _max2 = (y);			\
-	(void) (&_max1 == &_max2);		\
-	_max1 > _max2 ? _max1 : _max2; })
-
-#define MAX_CHUNK		4096
-#define PAGE_SIZE		4096
-
-#define pr_info(fmt, ...)				\
-	printf("%8d: " fmt, sys_gettid(), ##__VA_ARGS__)
-
-#define pr_err(fmt, ...)				\
-	printf("%8d: Error (%s:%d): " fmt, sys_gettid(),\
-		       __FILE__, __LINE__, ##__VA_ARGS__)
-
-#define pr_perror(fmt, ...)				\
-	pr_err(fmt ": %m\n", ##__VA_ARGS__)
-
-#define pr_msg(fmt, ...)				\
-	printf(fmt, ##__VA_ARGS__)
-
-
-#define pr_trace(fmt, ...)				\
-	printf("%8d: %s: " fmt, sys_gettid(), __func__,	\
-		##__VA_ARGS__)
-
-enum {
-	MEM_FILL_MODE_NONE	= 0,
-	MEM_FILL_MODE_ALL	= 1,
-	MEM_FILL_MODE_LIGHT	= 2,
-	MEM_FILL_MODE_DIRTIFY	= 3,
-};
-
-typedef struct {
-	pthread_mutex_t		mutex;
-	pthread_mutexattr_t	mutex_attr;
-
-	size_t			opt_tasks;
-
-	size_t			opt_files;
-	size_t			opt_file_size;
-	int			prev_fd[MAX_CHUNK];
-
-	size_t			opt_mem;
-	size_t			opt_mem_chunks;
-	size_t			opt_mem_chunk_size;
-	int			opt_mem_fill_mode;
-	int			opt_mem_cycle_mode;
-	unsigned int		opt_refresh_time;
-
-	char			*opt_work_dir;
-	int			work_dir_fd;
-	DIR			*work_dir;
-
-	pid_t			err_pid;
-	int			err_no;
-
-	unsigned long		prev_map[MAX_CHUNK];
-} shared_data_t;
-
-static shared_data_t *shared;
-
-static int sys_gettid(void)
-{
-	return syscall(__NR_gettid);
-}
-
-static void dirtify_memory(unsigned long *chunks, size_t nr_chunks,
-			   size_t chunk_size, int mode, const size_t nr_pages)
-{
-	void *page;
-	size_t i;
-
-	pr_trace("filling memory\n");
-	switch (mode) {
-	case MEM_FILL_MODE_LIGHT:
-		*((unsigned long *)chunks[0]) = -1ul;
-		break;
-	case MEM_FILL_MODE_ALL:
-		for (i = 0; i < nr_chunks; i++)
-			memset((void *)chunks[i], (char)i, chunk_size);
-		break;
-	case MEM_FILL_MODE_DIRTIFY:
-		for (i = 0; i < nr_chunks; i++)
-			*((unsigned long *)chunks[i]) = -1ul;
-		break;
-	}
-}
-
-static void dirtify_files(int *fd, size_t nr_files, size_t size)
-{
-	size_t buf[8192];
-	size_t i, j, c;
-
-	/*
-	 * Note we don't write any _sane_ data here, the only
-	 * important thing is I/O activity by self.
-	 */
-
-	for (i = 0; i < nr_files; i++) {
-		size_t c = min(size, sizeof(buf));
-		size_t left = size;
-
-		while (left > 0) {
-			write(fd[i], buf, c);
-			left -= c;
-			c = min(left, sizeof(buf));
-		}
-	}
-}
-
-static int create_files(shared_data_t *shared, int *fd, size_t nr_files)
-{
-	char path[PATH_MAX];
-	size_t i;
-
-	memset(fd, 0xff, sizeof(fd));
-
-	pr_info("\tCreating %lu files\n", shared->opt_files);
-
-	for (i = 0; i < shared->opt_files; i++) {
-		if (shared->prev_fd[i] != -1) {
-			close(shared->prev_fd[i]);
-			shared->prev_fd[i] = -1;
-		}
-		snprintf(path, sizeof(path), "%08d-%04d-temp", sys_gettid(), i);
-		fd[i] = openat(shared->work_dir_fd, path, O_RDWR | O_CREAT | O_TRUNC, 0666);
-		if (fd[i] < 0) {
-			pr_perror("Can't open %s/%s", shared->opt_work_dir, path);
-			shared->err_pid = sys_gettid();
-			shared->err_no = -errno;
-			return -1;
-		}
-		shared->prev_fd[i] = fd[i];
-	}
-
-	return 0;
-}
-
-static void work_on_fork(shared_data_t *shared)
-{
-	const size_t nr_pages = shared->opt_mem_chunk_size / PAGE_SIZE;
-	unsigned long chunks[MAX_CHUNK] = { };
-	int fd[MAX_CHUNK];
-	size_t i;
-	void *mem;
-
-	pr_trace("locking\n");
-	pthread_mutex_lock(&shared->mutex);
-	pr_trace("init\n");
-
-	pr_info("\tCreating %lu mmaps each %lu K\n",
-		shared->opt_mem_chunks, shared->opt_mem_chunk_size >> 10);
-
-	for (i = 0; i < shared->opt_mem_chunks; i++) {
-		if (shared->prev_map[i]) {
-			munmap((void *)shared->prev_map[i], shared->opt_mem_chunk_size);
-			shared->prev_map[i] = 0;
-		}
-
-		/* If we won't change proto here, the kernel might merge close areas */
-		mem = mmap(NULL, shared->opt_mem_chunk_size,
-			   PROT_READ | PROT_WRITE | ((i % 2) ? PROT_EXEC : 0),
-			   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-
-		if (mem != (void *)MAP_FAILED) {
-			shared->prev_map[i] = (unsigned long)mem;
-			chunks[i] = (unsigned long)mem;
-
-			pr_info("\t\tMap at %lx\n",(unsigned long)mem);
-		} else {
-			pr_info("\t\tCan't map\n");
-
-			shared->err_pid	= sys_gettid();
-			shared->err_no	= -errno;
-			exit(1);
-		}
-	}
-
-	if (shared->opt_mem_fill_mode)
-		dirtify_memory(chunks, shared->opt_mem_chunks,
-			       shared->opt_mem_chunk_size,
-			       shared->opt_mem_fill_mode,
-			       nr_pages);
-
-	if (create_files(shared, fd, shared->opt_files))
-		exit(1);
-
-	if (shared->opt_file_size)
-		dirtify_files(fd, shared->opt_files, shared->opt_file_size);
-
-		pr_trace("releasing\n");
-	pthread_mutex_unlock(&shared->mutex);
-
-	while (1) {
-		sleep(shared->opt_refresh_time);
-		if (shared->opt_mem_cycle_mode)
-			dirtify_memory(chunks, shared->opt_mem_chunks,
-				       shared->opt_mem_chunk_size,
-				       shared->opt_mem_cycle_mode,
-				       nr_pages);
-		if (shared->opt_file_size)
-			dirtify_files(fd, shared->opt_files, shared->opt_file_size);
-	}
-}
-
-static int parse_mem_mode(int *mode, char *opt)
-{
-	if (!strcmp(opt, "all")) {
-		*mode = MEM_FILL_MODE_ALL;
-	} else if (!strcmp(opt, "light")) {
-		*mode = MEM_FILL_MODE_LIGHT;
-	} else if (!strcmp(opt, "dirtify")) {
-		*mode = MEM_FILL_MODE_DIRTIFY;
-	} else {
-		pr_err("Unrecognized option %s\n", opt);
-		return -1;
-	}
-	return 0;
-}
-
-int main(int argc, char *argv[])
-{
-	/* a - 97, z - 122, A - 65, 90 */
-	static const char short_opts[] = "t:d:f:m:c:h";
-	static struct option long_opts[] = {
-		{"tasks",	required_argument, 0,	't'},
-		{"dir",		required_argument, 0,	'd'},
-		{"files",	required_argument, 0,	'f'},
-		{"memory",	required_argument, 0,	'm'},
-		{"mem-chunks",	required_argument, 0,	'c'},
-		{"help",	no_argument,       0,	'h'},
-		{"mem-fill",	required_argument, 0,	 10},
-		{"mem-cycle",	required_argument, 0,	 11},
-		{"refresh",	required_argument, 0,	 12},
-		{"file-size",	required_argument, 0,	 13},
-		{ },
-	};
-
-	char workdir[PATH_MAX];
-	int opt, idx, pidfd;
-	char pidbuf[32];
-	int status;
-	pid_t pid;
-	size_t i;
-
-	shared = (void *)mmap(NULL, sizeof(*shared), PROT_READ | PROT_WRITE,
-			      MAP_ANONYMOUS | MAP_SHARED, -1, 0);
-	if ((void *)shared == MAP_FAILED) {
-		pr_err("Failed to setup shared data\n");
-		exit(1);
-	}
-
-	pthread_mutexattr_init(&shared->mutex_attr);
-	pthread_mutexattr_setpshared(&shared->mutex_attr, PTHREAD_PROCESS_SHARED);
-	pthread_mutex_init(&shared->mutex, &shared->mutex_attr);
-
-	/*
-	 * Default options.
-	 */
-	shared->opt_mem_chunks = 1;
-	shared->opt_refresh_time = 1;
-	shared->opt_tasks = 1;
-	shared->opt_mem = 1 << 20ul;
-	memset(shared->prev_fd, 0xff, sizeof(shared->prev_fd));
-
-	while (1) {
-		idx = -1;
-		opt = getopt_long(argc, argv, short_opts, long_opts, &idx);
-		if (opt == -1)
-			break;
-
-		switch(opt) {
-		case 't':
-			shared->opt_tasks = (size_t)atol(optarg);
-			break;
-		case 'f':
-			shared->opt_files = (size_t)atol(optarg);
-			break;
-		case 'm':
-			/* In megabytes */
-			shared->opt_mem = (size_t)atol(optarg) << 20ul;
-			break;
-		case 'c':
-			shared->opt_mem_chunks = (size_t)atol(optarg);
-			break;
-		case 'd':
-			shared->opt_work_dir = optarg;
-			break;
-		case 'h':
-			goto usage;
-			break;
-		case 10:
-			if (parse_mem_mode(&shared->opt_mem_fill_mode, optarg))
-				goto usage;
-		case 11:
-			if (parse_mem_mode(&shared->opt_mem_cycle_mode, optarg))
-				goto usage;
-			break;
-		case 12:
-			shared->opt_refresh_time = (unsigned int)atoi(optarg);
-			break;
-		case 13:
-			shared->opt_file_size = (size_t)atol(optarg);
-		}
-	}
-
-	if (!shared->opt_work_dir) {
-		shared->opt_work_dir = getcwd(workdir, sizeof(workdir));
-		if (!shared->opt_work_dir)	{
-			pr_perror("Can't fetch current working dir");
-			exit(1);
-		}
-		shared->opt_work_dir = workdir;
-	}
-
-	if (shared->opt_mem_chunks > MAX_CHUNK)
-		shared->opt_mem_chunks = MAX_CHUNK;
-
-	if (shared->opt_files > MAX_CHUNK)
-		shared->opt_files = MAX_CHUNK;
-
-	shared->work_dir = opendir(shared->opt_work_dir);
-	if (!shared->work_dir) {
-		pr_perror("Can't open working dir `%s'",
-			  shared->opt_work_dir);
-		exit(1);
-	}
-	shared->work_dir_fd = dirfd(shared->work_dir);
-
-	shared->opt_mem_chunk_size = shared->opt_mem / shared->opt_mem_chunks;
-
-	if (shared->opt_mem_chunk_size &&
-	    shared->opt_mem_chunk_size < PAGE_SIZE) {
-		pr_err("Memory chunk size is too small, provide at least %lu M of memory\n",
-		       (shared->opt_mem_chunks * PAGE_SIZE) >> 20ul);
-		exit(1);
-	}
-
-	for (i = 0; i < shared->opt_tasks; i++) {
-		if (shared->err_no)
-			goto err_child;
-
-		pid = fork();
-		if (pid < 0) {
-			printf("Can't create fork: %m\n");
-			exit(1);
-		} else if (pid == 0) {
-			work_on_fork(shared);
-		}
-	}
-
-	/*
-	 * Once everything is done and we're in cycle,
-	 * create pidfile and go to sleep...
-	 */
-	pid = sys_gettid();
-	pidfd = openat(shared->work_dir_fd, "bers.pid", O_RDWR | O_CREAT | O_TRUNC, 0666);
-	if (pidfd < 0) {
-		pr_perror("Can't open pidfile");
-		exit(1);
-	}
-	snprintf(pidbuf, sizeof(pidbuf), "%d", sys_gettid());
-	write(pidfd, pidbuf, strlen(pidbuf));
-	close(pidfd);
-	pidfd = -1;
-
-	/*
-	 * Endless!
-	 */
-	while (!shared->err_no)
-		sleep(1);
-
-err_child:
-	pr_err("Child %d exited with %d\n",
-	       shared->err_pid, shared->err_no);
-	return shared->err_no;
-
-usage:
-	pr_msg("bers [options]\n");
-	pr_msg("    -t|--tasks <num>         create <num> of tasks\n");
-	pr_msg("    -d|--dir <dir>           use directory <dir> for temporary files\n");
-	pr_msg("    -f|--files <num>         create <num> files for each task\n");
-	pr_msg("    -m|--memory <num>        allocate <num> megabytes for each task\n");
-	pr_msg("    --memory-chunks <num>    split memory to <num> equal parts\n");
-	pr_msg("    --mem-fill <mode>        fill memory with data dependin on <mode>:\n");
-	pr_msg("                all          fill every byte of memory\n");
-	pr_msg("                light        fill first bytes of every page\n");
-	pr_msg("                dirtify      fill every page\n");
-	pr_msg("    --mem-cycle <mode>       same as --mem-fill but for cycling\n");
-	pr_msg("    --refresh <second>       refresh loading of every task each <second>\n");
-	pr_msg("    --file-size <bytes>      write <bytes> of data into each file on every refresh cycle\n");
-
-	return 1;
-}
diff --git a/test/bers/bers.txt b/test/bers/bers.txt
deleted file mode 100644
index 17c0c08..0000000
--- a/test/bers/bers.txt
+++ /dev/null
@@ -1,74 +0,0 @@
-bers(8)
-=======
-:doctype:       manpage
-:man source:    bers
-:man version:   0.0.1
-:man manual:    bers manual
-
-NAME
-----
-bers - go berserk and eat computer resources
-
-SYNOPSIS
---------
-*bers* ['options']
-
-DESCRIPTION
------------
-*bers* is a command line utility aimed to eat resources of the computer it runs on.
-Idea behind is to create a number of tasks which would trash computer resources
-eating cpu and i/o time.
-
-OPTIONS
--------
-*-t*, *--tasks* 'num'::
-	Create 'num' number of forks.
-
-*-d*, *--dir* 'dir'::
-	Path to 'dir' directory where temporary files will be created to load
-	I/O subsystem.
-
-*-f*, *--files* 'num'::
-	Create 'num' files in each task.
-
-*-m*, *--memory* 'num'::
-	Allocate 'num' megabytes of memory for every task.
-
-*--mem-chunks* 'num'::
-	Allocate memory for each task not as one slab but split
-	it into 'num' equal parts.
-
-*--mem-fill* 'mode'::
-	Touch (write) into allocated memory once task is created. The
-	'mode' might be one of the following: 'all' -- write every
-	single byte of the memory, 'light' -- write into first bytes
-	of first page of the allocated memory chunk, 'dirtify' -- write
-	into every page of every allocated chunk.
-
-*--mem-cycle* 'mode'::
-	Same as *--mem-fill*, but 'mode' taken into account while
-	task is cycling. By default each cycle initiated per one second.
-
-*--refresh* 'second'::
-	Refresh load state of every task each 'second'. By refsresh
-	here means to dirtify memory and file contents.
-
-*--file-size* 'bytes'::
-	Write 'bytes' of data into each file on every refresh cycle.
-
-EXAMPLE
--------
-
-bers -d test/bers/dump -t 256 -m 54 -c 4 -f 200 --mem-fill dirtify --mem-cycle dirtify
-
-We generate 256 tasks wit each allocating 54 megabytes of memory splitted
-equally into 4 memory areas. Each task opens 200 files. On creation and
-cycling we touch every page of every memory area.
-
-AUTHOR
-------
-OpenVZ team.
-
-COPYRIGHT
----------
-Copyright \(C) 2014, Parallels Inc.
diff --git a/test/ext-links/Makefile b/test/ext-links/Makefile
deleted file mode 100644
index 6b32c25..0000000
--- a/test/ext-links/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-all: mvlink.so
-
-mvlink.so: mvlink.c
-	gcc -g -Werror -Wall -shared -nostartfiles mvlink.c -o mvlink.so -iquote ../../include -fPIC
diff --git a/test/ext-links/addmv.sh b/test/ext-links/addmv.sh
deleted file mode 100755
index 0ccc971..0000000
--- a/test/ext-links/addmv.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-# $1 -- link name
-# $2 -- file with namespace pid
-if [ "$CRTOOLS_SCRIPT_ACTION" == "setup-namespaces" ]; then
-	$(dirname $0)/addmv_raw.sh $1 $(cat $2)
-else
-	exit 0
-fi
diff --git a/test/ext-links/addmv_raw.sh b/test/ext-links/addmv_raw.sh
deleted file mode 100755
index 224f243..0000000
--- a/test/ext-links/addmv_raw.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-# $1 -- link name
-# $2 -- pid of task in namespace
-set -x
-$ip link add link eth0 name $1 type macvlan || exit 1
-$ip link set $1 netns $2
diff --git a/test/ext-links/mvlink.c b/test/ext-links/mvlink.c
deleted file mode 100644
index a1c764d..0000000
--- a/test/ext-links/mvlink.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "criu-plugin.h"
-#include "criu-log.h"
-
-extern cr_plugin_init_t cr_plugin_init;
-extern cr_plugin_dump_ext_link_t cr_plugin_dump_ext_link;
-
-int cr_plugin_init(void)
-{
-	pr_info("Initialized macvlan dumper\n");
-	return 0;
-}
-
-int cr_plugin_dump_ext_link(int index, int type, char *kind)
-{
-	if (strcmp(kind, "macvlan"))
-		return -ENOTSUP;
-	else {
-		pr_info("Dump %d macvlan\n", index);
-		return 0;
-	}
-}
diff --git a/test/ext-links/run.sh b/test/ext-links/run.sh
deleted file mode 100755
index a48b73a..0000000
--- a/test/ext-links/run.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/bash
-
-ip=${CR_IP_TOOL:-ip}
-mvln="mv0"
-finf="finish"
-outf="ns_output"
-pidf="ns_pid"
-criu="../../criu/criu"
-
-export ip
-export mvln
-export finf
-export outf
-export pidf
-
-function fail {
-	$ip link del $mvln
-	touch $finf
-	echo $@
-	exit 1
-}
-
-# Build the mvlink plugin
-make
-
-set -x
-
-rm -f "$finf" "$outf" "$pidf"
-rm -rf "dump"
-
-# Unshare netns. The run_ns will exit once ns is spawned.
-unshare --net ./run_ns.sh
-nspid=$(cat $pidf)
-ps $nspid
-
-# Create and push macvlan device into it. CRIU doesn't support
-# macvlans treating them as external devices.
-./addmv_raw.sh $mvln $nspid || fail "Can't setup namespace"
-
-# Dump
-sleep 1
-mkdir dump
-$criu dump -t $nspid -D dump/ -o dump.log -v4 --lib $(pwd) || fail "Can't dump namespace"
-
-# Restore
-# Ask for the pid (shouldn't change, so just as an example), ask to call
-# script that will put macvlan device back into namespace
-sleep 1
-rm -f $pidf
-$criu restore -D dump/ -o restore.log -v4 --pidfile $(pwd)/$pidf --action-script "$(pwd)/addmv.sh $mvln $(pwd)/$pidf" -d || fail "Can't restore namespaces"
-
-# Finish and check results
-touch $finf
-set +x
-while ! egrep 'PASS|FAIL' $outf; do
-	echo "Waiting"
-	sleep 1
-done
diff --git a/test/ext-links/run_ns.sh b/test/ext-links/run_ns.sh
deleted file mode 100755
index 878f038..0000000
--- a/test/ext-links/run_ns.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-set -x
-echo "NS: $$" >> $outf
-echo "Links before:" >> $outf
-$ip link list >> $outf 2>&1
-# Detach from session, terminal and parent
-setsid ./run_wait.sh < /dev/null >> $outf 2>&1 &
-# Keep pid for future reference :)
-echo "$!" > $pidf
-exit 0
diff --git a/test/ext-links/run_wait.sh b/test/ext-links/run_wait.sh
deleted file mode 100755
index d600e37..0000000
--- a/test/ext-links/run_wait.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-echo "Wait: $$"
-while [ ! -e "$finf" ]; do
-	echo "WAIT ($$)"
-	sleep 1;
-done
-
-echo "Links after:"
-$ip link list
-
-# The mvln device (exported from run.sh) should exits in
-# namespace after we get restored
-echo "Check for $mvln:"
-$ip link list $mvln && echo "PASS" || echo "FAIL"
diff --git a/test/ext-tty/run.py b/test/ext-tty/run.py
deleted file mode 100755
index 16fe0f6..0000000
--- a/test/ext-tty/run.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import subprocess
-import pty
-import os, sys, time
-
-master, slave = pty.openpty()
-
-p = subprocess.Popen(["setsid", "--ctty", "sleep", "10000"],
-			stdin = slave, stdout = slave, stderr = slave, close_fds = True)
-st = os.stat("/proc/self/fd/%d" % slave)
-ttyid = "tty[%x:%x]" % (st.st_rdev, st.st_dev)
-os.close(slave)
-time.sleep(1)
-
-ret = subprocess.Popen(["../../criu/criu", "dump", "-t", str(p.pid), "-v4", "--external", ttyid]).wait()
-if ret:
-	sys.exit(ret)
-p.wait()
-
-new_master, slave = pty.openpty() # get another pty pair
-os.close(master)
-
-ttyid = "fd[%d]:tty[%x:%x]" % (slave, st.st_rdev, st.st_dev)
-
-ret = subprocess.Popen(["../../criu/criu", "restore", "-v4", "--inherit-fd", ttyid, "--restore-sibling", "--restore-detach"]).wait()
-if ret:
-	sys.exit(ret)
-os.close(slave)
-os.waitpid(-1, os.WNOHANG) # is the process alive
-
-os.close(new_master)
-_, status = os.wait()
-if not os.WIFSIGNALED(status) or not os.WTERMSIG(status):
-	print status
-	sys.exit(1)
-
-print "PASS"
diff --git a/test/fault-injection/Makefile b/test/fault-injection/Makefile
deleted file mode 100644
index 1b31e8a..0000000
--- a/test/fault-injection/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-all:
-	stap -g -d ../../criu/criu parasite.stp $$RANDOM -c 'bash -x ../zdtm.sh -d -x socket-tcp'
diff --git a/test/fault-injection/parasite.stp b/test/fault-injection/parasite.stp
deleted file mode 100644
index c1b0818..0000000
--- a/test/fault-injection/parasite.stp
+++ /dev/null
@@ -1,44 +0,0 @@
-global i, n, fini_cmd = -1, last_cmd
-
-probe process("../../criu/criu").begin
-{
-	i = 0;
-	/* randint() returns numbers multiple of 5 */
-	n = randint(20 * 5) / 5
-	printf("The %d command will be replaced on -1\n", n);
-}
-
-probe process("../../criu/criu").function("__parasite_execute_daemon")
-{
-	printf("%s\n", $$parms);
-	last_cmd = $cmd;
-	if (++i > n) {
-		printf("Send invalid command to parasite\n");
-		$cmd = -1;
-	}
-}
-
-probe process("../../criu/criu").function("__parasite_execute_daemon").return
-{
-	printf("%d\n", $return);
-}
-
-probe process("../../criu/criu").function("main").return
-{
-	printf("CRIU exits with code %d\n", $return);
-	if  ( i > n) {
-		if ($return)
-			$return = 0;
-		else {
-			printf("CRIU exited with zero code\n");
-			if (fini_cmd < 0 || fini_cmd == last_cmd) {
-				printf("%d looks like FINI command\n", n);
-				fini_cmd = last_cmd
-			} else {
-				printf("This is the second FINI command %d (%d)",
-								n, fini_cmd);
-				$return = 1;
-			}
-		}
-	}
-}
diff --git a/test/libcriu/.gitignore b/test/libcriu/.gitignore
deleted file mode 100644
index 6424681..0000000
--- a/test/libcriu/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-test_errno
-test_iters
-test_notify
-test_self
-test_sub
-wdir
diff --git a/test/libcriu/Makefile b/test/libcriu/Makefile
deleted file mode 100644
index 459ae61..0000000
--- a/test/libcriu/Makefile
+++ /dev/null
@@ -1,26 +0,0 @@
-TESTS += test_sub 
-TESTS += test_self
-TESTS += test_notify
-TESTS += test_iters
-TESTS += test_errno
-
-all: $(TESTS)
-
-run: all
-	./run.sh
-
-define genb
-$(1): $(1).o lib.o
-	gcc $$^ -L ../../lib -L ../../protobuf -lcriu -o $$@
-endef
-
-$(foreach t, $(TESTS), $(eval $(call genb, $(t))))
-
-%.o: %.c
-	gcc -c $^ -I../../lib/ -I../../protobuf -o $@ -Werror
-
-clean:
-	rm -rf $(TESTS) $(TESTS:%=%.o) lib.o
-
-.PHONY: clean
-.PHONY: all
diff --git a/test/libcriu/lib.c b/test/libcriu/lib.c
deleted file mode 100644
index 33aa409..0000000
--- a/test/libcriu/lib.c
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <stdio.h>
-#include <errno.h>
-#include <sys/wait.h>
-
-void what_err_ret_mean(int ret)
-{
-	/* NOTE: errno is set by libcriu */
-	switch (ret) {
-	case -EBADE:
-		perror("RPC has returned fail");
-		break;
-	case -ECONNREFUSED:
-		perror("Unable to connect to CRIU");
-		break;
-	case -ECOMM:
-		perror("Unable to send/recv msg to/from CRIU");
-		break;
-	case -EINVAL:
-		perror("CRIU doesn't support this type of request."
-		       "You should probably update CRIU");
-		break;
-	case -EBADMSG:
-		perror("Unexpected response from CRIU."
-		       "You should probably update CRIU");
-		break;
-	default:
-		perror("Unknown error type code."
-		       "You should probably update CRIU");
-	}
-}
-
-int chk_exit(int status, int want)
-{
-	if (WIFEXITED(status)) {
-		if (WEXITSTATUS(status) == want)
-			return 0;
-
-		printf("   `- FAIL (exit %d)\n", WEXITSTATUS(status));
-	} else if (WIFSIGNALED(status))
-		printf("   `- FAIL (die %d)\n", WTERMSIG(status));
-	else
-		printf("   `- FAIL (%#x)\n", status);
-
-	return 1;
-}
-
-
diff --git a/test/libcriu/lib.h b/test/libcriu/lib.h
deleted file mode 100644
index 67b784b..0000000
--- a/test/libcriu/lib.h
+++ /dev/null
@@ -1,2 +0,0 @@
-void what_err_ret_mean(int ret);
-int chk_exit(int status, int want);
diff --git a/test/libcriu/run.sh b/test/libcriu/run.sh
deleted file mode 100755
index 51ed141..0000000
--- a/test/libcriu/run.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/bash
-
-source ../env.sh || exit 1
-
-echo "== Clean"
-make clean
-rm -rf wdir
-rm -f ./libcriu.so.1
-
-echo "== Prepare"
-mkdir -p wdir/i/
-
-echo "== Run tests"
-ln -s ../../lib/libcriu.so libcriu.so.1
-export LD_LIBRARY_PATH=.
-export PATH="`dirname ${BASH_SOURCE[0]}`/../../:$PATH"
-
-RESULT=0
-
-function run_test {
-	echo "== Build $1"
-	if ! make $1; then
-		echo "FAIL build $1"
-		RESULT=1;
-	else
-		echo "== Test $1"
-		mkdir wdir/i/$1/
-		if ! setsid ./$1 ${CRIU} wdir/i/$1/ < /dev/null &>> wdir/i/$1/test.log; then
-			echo "$1: FAIL"
-			RESULT=1
-		fi
-	fi
-}
-
-run_test test_sub
-run_test test_self
-run_test test_notify
-run_test test_iters
-run_test test_errno
-
-echo "== Tests done"
-unlink libcriu.so.1
-[ $RESULT -eq 0 ] && echo "Success" || echo "FAIL"
-exit $RESULT
diff --git a/test/libcriu/test_errno.c b/test/libcriu/test_errno.c
deleted file mode 100644
index e091443..0000000
--- a/test/libcriu/test_errno.c
+++ /dev/null
@@ -1,154 +0,0 @@
-#include "criu.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h>
-
-#define PID_MAX "/proc/sys/kernel/pid_max"
-
-static int dir_fd;
-static char *service;
-
-static int init(char *argv[])
-{
-	service = argv[1];
-
-	dir_fd = open(argv[2], O_DIRECTORY);
-	if (dir_fd < 0) {
-		perror("Can't open images dir");
-		return -1;
-	}
-
-	return 0;
-}
-
-static void get_base_req(void)
-{
-	criu_init_opts();
-	criu_set_service_binary(service);
-	criu_set_images_dir_fd(dir_fd);
-	criu_set_log_level(4);
-}
-
-static int check_resp(int ret, int expected_ret, int err, int expected_err)
-{
-	if (ret != expected_ret) {
-		fprintf(stderr, "Unexpected ret %d (%d expected)\n", ret, expected_ret);
-		return -1;
-	}
-
-	if (err != expected_err) {
-		fprintf(stderr, "Unexpected errno %d (%d expected)\n", err, expected_err);
-		return -1;
-	}
-
-	return 0;
-}
-
-static int no_process(void)
-{
-	FILE *f = NULL;
-	size_t len;
-	ssize_t count;
-	char *buf = NULL;
-	int pid, fd, ret;
-
-	printf("--- Try to dump unexisting process\n");
-
-	f = fopen(PID_MAX, "r");
-	if (!f) {
-		perror("Can't open " PID_MAX);
-		goto err;
-	}
-
-	count = getline(&buf, &len, f);
-	if (count == -1) {
-		perror("Can't read " PID_MAX);
-		goto err;
-	}
-	pid = atoi(buf);
-
-	if (!kill(pid, 0)) {
-		fprintf(stderr, "max pid is taken\n");
-		goto err;
-	}
-
-	get_base_req();
-	criu_set_pid(pid);
-	ret = criu_dump();
-	if (check_resp(ret, -EBADE, errno, ESRCH))
-		goto err;
-
-	printf("   `- Success\n");
-	return 0;
-err:
-	if (f)
-		fclose(f);
-	return -1;
-
-}
-
-static int process_exists(void)
-{
-	int ret;
-
-	printf("--- Try to restore process which pid is already taken by other process\n");
-
-	get_base_req();
-	criu_set_leave_running(true);
-	if (criu_dump()) {
-		fprintf(stderr, "Self-dump failed");
-		goto err;
-	}
-
-	get_base_req();
-	ret = criu_restore();
-	if (check_resp(ret, -EBADE, errno, EEXIST))
-		goto err;
-
-	printf("   `- Success\n");
-	return 0;
-err:
-	return -1;
-}
-
-static int bad_options(void)
-{
-	int ret;
-
-	printf("--- Try to send criu invalid opts\n");
-
-	get_base_req();
-	criu_set_log_file("../file.log");
-	ret = criu_dump();
-	if (check_resp(ret, -EBADE, errno, EBADRQC))
-		goto err;
-
-	printf("   `- Success\n");
-	return 0;
-err:
-	return -1;
-}
-
-int main(int argc, char *argv[])
-{
-	int ret = 1;
-
-	if (init(argv))
-		goto out;
-
-	if (no_process() || process_exists() || bad_options())
-		goto out;
-
-	ret = 0;
-out:
-	if (dir_fd)
-		close(dir_fd);
-
-	return ret;
-}
diff --git a/test/libcriu/test_iters.c b/test/libcriu/test_iters.c
deleted file mode 100644
index 660da92..0000000
--- a/test/libcriu/test_iters.c
+++ /dev/null
@@ -1,143 +0,0 @@
-#include "criu.h"
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include "lib.h"
-
-static int wdir_fd, cur_iter = 1, cur_imgdir = -1;
-
-static int stop = 0;
-static void sh(int sig)
-{
-	stop = 1;
-}
-
-static int open_imgdir(void)
-{
-	char p[10];
-
-	sprintf(p, "%d", cur_iter);
-	mkdirat(wdir_fd, p, 0700);
-	cur_imgdir = openat(wdir_fd, p, O_DIRECTORY);
-	criu_set_images_dir_fd(cur_imgdir);
-}
-
-#define MAX_ITERS	2
-
-static int next_iter(criu_predump_info pi)
-{
-	char p[10];
-
-	printf("   `- %d iter over\n", cur_iter);
-
-	close(cur_imgdir);
-	sprintf(p, "../%d", cur_iter);
-	criu_set_parent_images(p);
-
-	cur_iter++;
-	open_imgdir();
-
-	return cur_iter < MAX_ITERS;
-}
-
-#define SUCC_ECODE	42
-
-int main(int argc, char **argv)
-{
-	int pid, ret, p[2];
-
-	wdir_fd = open(argv[2], O_DIRECTORY);
-	if (wdir_fd < 0) {
-		perror("Can't open wdir");
-		return 1;
-	}
-
-	printf("--- Start loop ---\n");
-	pipe(p);
-	pid = fork();
-	if (pid < 0) {
-		perror("Can't");
-		return -1;
-	}
-
-	if (!pid) {
-		printf("   `- loop: initializing\n");
-		if (setsid() < 0)
-			exit(1);
-		if (signal(SIGUSR1, sh) == SIG_ERR)
-			exit(1);
-
-		close(0);
-		close(1);
-		close(2);
-		close(p[0]);
-
-		ret = SUCC_ECODE;
-		write(p[1], &ret, sizeof(ret));
-		close(p[1]);
-
-		while (!stop)
-			sleep(1);
-		exit(SUCC_ECODE);
-	}
-
-	close(p[1]);
-
-	/* Wait for kid to start */
-	ret = -1;
-	read(p[0], &ret, sizeof(ret));
-	if (ret != SUCC_ECODE) {
-		printf("Error starting loop\n");
-		goto err;
-	}
-
-	/* Wait for pipe to get closed, then dump */
-	read(p[0], &ret, 1);
-	close(p[0]);
-
-	printf("--- Dump loop ---\n");
-	criu_init_opts();
-	criu_set_service_binary(argv[1]);
-	criu_set_pid(pid);
-	criu_set_log_file("dump.log");
-	criu_set_log_level(4);
-
-	open_imgdir();
-	ret = criu_dump_iters(next_iter);
-	if (ret < 0) {
-		what_err_ret_mean(ret);
-		kill(pid, SIGKILL);
-		goto err;
-	}
-
-	printf("   `- Dump succeeded\n");
-	waitpid(pid, NULL, 0);
-
-	printf("--- Restore loop ---\n");
-	criu_init_opts();
-	criu_set_log_level(4);
-	criu_set_log_file("restore.log");
-	criu_set_images_dir_fd(cur_imgdir);
-
-	pid = criu_restore_child();
-	if (pid <= 0) {
-		what_err_ret_mean(pid);
-		return -1;
-	}
-
-	printf("   `- Restore returned pid %d\n", pid);
-	kill(pid, SIGUSR1);
-err:
-	if (waitpid(pid, &ret, 0) < 0) {
-		perror("   Can't wait kid");
-		return -1;
-	}
-
-	return chk_exit(ret, SUCC_ECODE);
-}
diff --git a/test/libcriu/test_notify.c b/test/libcriu/test_notify.c
deleted file mode 100644
index 54fb255..0000000
--- a/test/libcriu/test_notify.c
+++ /dev/null
@@ -1,97 +0,0 @@
-#include "criu.h"
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include "lib.h"
-
-#define SUCC_ECODE	42
-
-static int actions_called = 0;
-static int notify(char *action, criu_notify_arg_t na)
-{
-	printf("ACTION: %s\n", action);
-	actions_called++;
-	return 0;
-}
-
-int main(int argc, char **argv)
-{
-	int pid, ret, fd, p[2];
-
-	printf("--- Start loop ---\n");
-	pipe(p);
-	pid = fork();
-	if (pid < 0) {
-		perror("Can't");
-		return -1;
-	}
-
-	if (!pid) {
-		printf("   `- loop: initializing\n");
-		if (setsid() < 0)
-			exit(1);
-
-		close(0);
-		close(1);
-		close(2);
-		close(p[0]);
-
-		ret = SUCC_ECODE;
-		write(p[1], &ret, sizeof(ret));
-		close(p[1]);
-
-		while (1)
-			sleep(1);
-
-		exit(SUCC_ECODE);
-	}
-
-	close(p[1]);
-
-	/* Wait for kid to start */
-	ret = -1;
-	read(p[0], &ret, sizeof(ret));
-	if (ret != SUCC_ECODE) {
-		printf("Error starting loop\n");
-		goto err;
-	}
-
-	/* Wait for pipe to get closed, then dump */
-	read(p[0], &ret, 1);
-	close(p[0]);
-
-	printf("--- Dump loop ---\n");
-	criu_init_opts();
-	criu_set_service_binary(argv[1]);
-	criu_set_pid(pid);
-	criu_set_log_file("dump.log");
-	criu_set_log_level(4);
-	criu_set_notify_cb(notify);
-	fd = open(argv[2], O_DIRECTORY);
-	criu_set_images_dir_fd(fd);
-
-	ret = criu_dump();
-	if (ret < 0) {
-		what_err_ret_mean(ret);
-		kill(pid, SIGKILL);
-		goto err;
-	}
-
-	printf("   `- Dump succeeded\n");
-	ret = 0;
-err:
-	waitpid(pid, NULL, 0);
-	if (ret || !actions_called) {
-		printf("FAIL (%d/%d)\n", ret, actions_called);
-		return 1;
-	}
-
-	printf("   `- Success (%d actions)\n", actions_called);
-	return 0;
-}
diff --git a/test/libcriu/test_self.c b/test/libcriu/test_self.c
deleted file mode 100644
index c9d2a2e..0000000
--- a/test/libcriu/test_self.c
+++ /dev/null
@@ -1,96 +0,0 @@
-#include "criu.h"
-#include <unistd.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include "lib.h"
-
-#define SUCC_DUMP_ECODE	41
-#define SUCC_RSTR_ECODE	43
-
-int main(int argc, char *argv[])
-{
-	int ret, fd, pid;
-
-	fd = open(argv[2], O_DIRECTORY);
-	if (fd < 0) {
-		perror("Can't open images dir");
-		return 1;
-	}
-
-	criu_init_opts();
-	criu_set_service_binary(argv[1]);
-	criu_set_images_dir_fd(fd);
-	criu_set_log_level(4);
-
-	printf("--- Start child ---\n");
-	pid = fork();
-	if (pid < 0) {
-		perror("Can't");
-		return 1;
-	}
-
-	if (!pid) {
-		/*
-		 * Child process -- dump itself, then
-		 * parent would restore us.
-		 */
-
-		close(0);
-		close(1);
-		close(2);
-		if (setsid() < 0)
-			exit(1);
-
-		criu_set_log_file("dump.log");
-		criu_set_leave_running(true);
-		ret = criu_dump();
-		if (ret < 0) {
-			what_err_ret_mean(ret);
-			exit(1);
-		}
-
-		if (ret == 0)
-			ret = SUCC_DUMP_ECODE; /* dumped OK */
-		else if (ret == 1)
-			ret = SUCC_RSTR_ECODE; /* restored OK */
-		else
-			ret = 1;
-
-		exit(ret);
-	}
-
-	printf("--- Wait for self-dump ---\n");
-	if (waitpid(pid, &ret, 0) < 0) {
-		perror("Can't wait child");
-		goto errk;
-	}
-
-	if (chk_exit(ret, SUCC_DUMP_ECODE))
-		goto errk;
-
-	printf("--- Restore ---\n");
-	criu_set_log_file("restore.log");
-
-	pid = criu_restore_child();
-	if (pid <= 0) {
-		what_err_ret_mean(pid);
-		goto err;
-	}
-
-	if (waitpid(pid, &ret, 0) < 0) {
-		perror("Can't wait rchild");
-		goto errk;
-	}
-
-	return chk_exit(ret, SUCC_RSTR_ECODE);
-
-errk:
-	kill(pid, SIGKILL);
-err:
-	return 1;
-
-}
diff --git a/test/libcriu/test_sub.c b/test/libcriu/test_sub.c
deleted file mode 100644
index b435f67..0000000
--- a/test/libcriu/test_sub.c
+++ /dev/null
@@ -1,107 +0,0 @@
-#include "criu.h"
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include "lib.h"
-
-static int stop = 0;
-static void sh(int sig)
-{
-	stop = 1;
-}
-
-#define SUCC_ECODE	42
-
-int main(int argc, char **argv)
-{
-	int pid, ret, fd, p[2];
-
-	printf("--- Start loop ---\n");
-	pipe(p);
-	pid = fork();
-	if (pid < 0) {
-		perror("Can't");
-		return -1;
-	}
-
-	if (!pid) {
-		printf("   `- loop: initializing\n");
-		if (setsid() < 0)
-			exit(1);
-		if (signal(SIGUSR1, sh) == SIG_ERR)
-			exit(1);
-
-		close(0);
-		close(1);
-		close(2);
-		close(p[0]);
-
-		ret = SUCC_ECODE;
-		write(p[1], &ret, sizeof(ret));
-		close(p[1]);
-
-		while (!stop)
-			sleep(1);
-		exit(SUCC_ECODE);
-	}
-
-	close(p[1]);
-
-	/* Wait for kid to start */
-	ret = -1;
-	read(p[0], &ret, sizeof(ret));
-	if (ret != SUCC_ECODE) {
-		printf("Error starting loop\n");
-		goto err;
-	}
-
-	/* Wait for pipe to get closed, then dump */
-	read(p[0], &ret, 1);
-	close(p[0]);
-
-	printf("--- Dump loop ---\n");
-	criu_init_opts();
-	criu_set_service_binary(argv[1]);
-	criu_set_pid(pid);
-	criu_set_log_file("dump.log");
-	criu_set_log_level(4);
-	fd = open(argv[2], O_DIRECTORY);
-	criu_set_images_dir_fd(fd);
-
-	ret = criu_dump();
-	if (ret < 0) {
-		what_err_ret_mean(ret);
-		kill(pid, SIGKILL);
-		goto err;
-	}
-
-	printf("   `- Dump succeeded\n");
-	waitpid(pid, NULL, 0);
-
-	printf("--- Restore loop ---\n");
-	criu_init_opts();
-	criu_set_log_level(4);
-	criu_set_log_file("restore.log");
-	criu_set_images_dir_fd(fd);
-
-	pid = criu_restore_child();
-	if (pid <= 0) {
-		what_err_ret_mean(pid);
-		return -1;
-	}
-
-	printf("   `- Restore returned pid %d\n", pid);
-	kill(pid, SIGUSR1);
-err:
-	if (waitpid(pid, &ret, 0) < 0) {
-		perror("   Can't wait kid");
-		return -1;
-	}
-
-	return chk_exit(ret, SUCC_ECODE);
-}
diff --git a/test/mem-snap/Makefile b/test/mem-snap/Makefile
deleted file mode 100644
index 7779a99..0000000
--- a/test/mem-snap/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-run:
-	./run.sh
diff --git a/test/mem-snap/run-predump-2.sh b/test/mem-snap/run-predump-2.sh
deleted file mode 100755
index 2717cde..0000000
--- a/test/mem-snap/run-predump-2.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/bash
-
-source ../env.sh || exit 1
-
-function fail {
-	echo "$@"
-	exit 1
-}
-set -x
-
-IMGDIR="dump/"
-
-rm -rf "$IMGDIR"
-mkdir "$IMGDIR"
-
-function launch_test {
-	echo "Launching test"
-	cd ../zdtm/live/static/
-	make cleanout
-	make maps04
-	make maps04.pid || fail "Can't start test"
-	PID=$(cat maps04.pid)
-	kill -0 $PID || fail "Test didn't start"
-	cd -
-}
-
-function stop_test {
-	wtime=1
-	cd ../zdtm/live/static/
-	make maps04.stop
-	cat maps04.out | fgrep PASS || fail "Test failed"
-	echo "OK"
-}
-
-launch_test
-
-echo "Taking plain dump"
-
-mkdir "$IMGDIR/dump-1/"
-${CRIU} dump -D "$IMGDIR/dump-1/" -o dump.log -t ${PID} -v4 || fail "Fail to dump"
-
-sleep 1
-echo "Restore to check it works"
-${CRIU} restore -D "${IMGDIR}/dump-1/" -o restore.log -d -v4 || fail "Fail to restore server"
-
-stop_test
-
-
-launch_test
-
-echo "Taking pre and plain dumps"
-
-echo "Pre-dump"
-mkdir "$IMGDIR/dump-2/"
-mkdir "$IMGDIR/dump-2/pre/"
-${CRIU} pre-dump -D "$IMGDIR/dump-2/pre/" -o dump.log -t ${PID} -v4 || fail "Fail to pre-dump"
-
-echo "Plain dump"
-mkdir "$IMGDIR/dump-2/plain/"
-${CRIU} dump -D "$IMGDIR/dump-2/plain/" -o dump.log -t ${PID} -v4 --prev-images-dir=../pre/ --track-mem || fail "Fail to dump"
-
-sleep 1
-echo "Restore"
-${CRIU} restore -D "${IMGDIR}/dump-2/plain/" -o restore.log -d -v4 || fail "Fail to restore server"
-
-stop_test
diff --git a/test/mem-snap/run-predump.sh b/test/mem-snap/run-predump.sh
deleted file mode 100755
index e25ccfd..0000000
--- a/test/mem-snap/run-predump.sh
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/bash
-
-source ../env.sh || exit 1
-
-USEPS=0
-
-if [ "$1" = "-s" ]; then
-	echo "Will test via page-server"
-	USEPS=1
-	shift
-fi
-
-NRSNAP=${1:-3}
-SPAUSE=${2:-4}
-PORT=12345
-
-function fail {
-	echo "$@"
-	exit 1
-}
-set -x
-
-IMGDIR="dump/"
-
-rm -rf "$IMGDIR"
-mkdir "$IMGDIR"
-
-echo "Launching test"
-cd ../zdtm/live/static/
-make cleanout
-make mem-touch
-make mem-touch.pid || fail "Can't start test"
-PID=$(cat mem-touch.pid)
-kill -0 $PID || fail "Test didn't start"
-cd -
-
-echo "Making $NRSNAP pre-dumps"
-
-for SNAP in $(seq 1 $NRSNAP); do
-	sleep $SPAUSE
-	mkdir "$IMGDIR/$SNAP/"
-	if [ $SNAP -eq 1 ] ; then
-		# First pre-dump
-		cmd="pre-dump"
-		args="--track-mem -R"
-	elif [ $SNAP -eq $NRSNAP ]; then
-		# Last dump
-		cmd="dump"
-		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem"
-	else
-		# Other pre-dumps
-		cmd="pre-dump"
-		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem -R"
-	fi
-
-	if [ $USEPS -eq 1 ]; then
-		${CRIU} page-server -D "${IMGDIR}/$SNAP/" -o ps.log --port ${PORT} -v4 &
-		PS_PID=$!
-		ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
-	else
-		ps_args=""
-	fi
-
-	${CRIU} $cmd -D "${IMGDIR}/$SNAP/" -o dump.log -t ${PID} -v4 $args $ps_args || fail "Fail to dump"
-	if [ $USEPS -eq 1 ]; then
-		wait $PS_PID
-	fi
-done
-
-echo "Restoring"
-${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log -d -v4 || fail "Fail to restore server"
-
-cd ../zdtm/live/static/
-make mem-touch.stop
-cat mem-touch.out | fgrep PASS || fail "Test failed"
-
-echo "Test PASSED"
diff --git a/test/mem-snap/run-snap-auto-dedup.sh b/test/mem-snap/run-snap-auto-dedup.sh
deleted file mode 100755
index f4eb119..0000000
--- a/test/mem-snap/run-snap-auto-dedup.sh
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/bin/bash
-
-source ../env.sh || exit 1
-
-USEPS=0
-
-if [ "$1" = "-s" ]; then
-	echo "Will test via page-server"
-	USEPS=1
-	shift
-fi
-
-NRSNAP=${1:-3}
-SPAUSE=${2:-4}
-PORT=12345
-
-function fail {
-	echo "$@"
-	exit 1
-}
-set -x
-
-IMGDIR="dump/"
-
-rm -rf "$IMGDIR"
-mkdir "$IMGDIR"
-
-echo "Launching test"
-cd ../zdtm/live/static/
-make cleanout
-make mem-touch
-make mem-touch.pid || fail "Can't start test"
-PID=$(cat mem-touch.pid)
-kill -0 $PID || fail "Test didn't start"
-cd -
-
-echo "Making $NRSNAP snapshots"
-
-for SNAP in $(seq 1 $NRSNAP); do
-	sleep $SPAUSE
-	mkdir "$IMGDIR/$SNAP/"
-	if [ $SNAP -eq 1 ] ; then
-		# First snapshot -- no parent, keep running
-		args="--track-mem -R"
-	elif [ $SNAP -eq $NRSNAP ]; then
-		# Last snapshot -- has parent, kill afterwards
-		size_first_2=$(du -sh -BK  dump/2/pages-*.img | grep -Eo '[0-9]+' | head -1)
-		size_first_1=$(du -sh -BK  dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
-		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem --auto-dedup"
-	else
-		# Other snapshots -- have parent, keep running
-		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem -R"
-	fi
-
-	if [ $USEPS -eq 1 ]; then
-		${CRIU} page-server -D "${IMGDIR}/$SNAP/" -o ps.log --auto-dedup --port ${PORT} -v4 &
-		PS_PID=$!
-		ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
-	else
-		ps_args=""
-	fi
-
-	${CRIU} dump -D "${IMGDIR}/$SNAP/" -o dump.log -t ${PID} -v4 $args $ps_args || fail "Fail to dump"
-	if [ $USEPS -eq 1 ]; then
-		wait $PS_PID
-	fi
-done
-
-size_last_2=$(du -sh -BK dump/2/pages-*.img | grep -Eo '[0-9]+' | head -1)
-size_last_1=$(du -sh -BK dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
-
-dedup_ok_2=1
-if [ $size_first_2 -gt $size_last_2 ]; then
-	dedup_ok_2=0
-fi
-
-dedup_ok_1=1
-if [ $size_first_1 -gt $size_last_1 ]; then
-	dedup_ok_1=0
-fi
-
-echo "Restoring"
-${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log -d -v4 || fail "Fail to restore server"
-
-cd ../zdtm/live/static/
-make mem-touch.stop
-cat mem-touch.out | fgrep PASS || fail "Test failed"
-
-if [[ $dedup_ok_2 -ne 0 || $dedup_ok_1 -ne 0 ]]; then
-	fail "Dedup test failed"
-fi
-
-echo "Test PASSED"
diff --git a/test/mem-snap/run-snap-dedup-on-restore.sh b/test/mem-snap/run-snap-dedup-on-restore.sh
deleted file mode 100755
index 7bfdf0e..0000000
--- a/test/mem-snap/run-snap-dedup-on-restore.sh
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/bin/bash
-
-source ../env.sh || exit 1
-
-USEPS=0
-
-if [ "$1" = "-s" ]; then
-	echo "Will test via page-server"
-	USEPS=1
-	shift
-fi
-
-NRSNAP=${1:-3}
-SPAUSE=${2:-4}
-PORT=12345
-
-function fail {
-	echo "$@"
-	exit 1
-}
-set -x
-
-IMGDIR="dump/"
-
-rm -rf "$IMGDIR"
-mkdir "$IMGDIR"
-
-echo "Launching test"
-cd ../zdtm/live/static/
-make cleanout
-make mem-touch
-make mem-touch.pid || fail "Can't start test"
-PID=$(cat mem-touch.pid)
-kill -0 $PID || fail "Test didn't start"
-cd -
-
-echo "Making $NRSNAP snapshots"
-
-for SNAP in $(seq 1 $NRSNAP); do
-	sleep $SPAUSE
-	mkdir "$IMGDIR/$SNAP/"
-	if [ $SNAP -eq 1 ] ; then
-		# First snapshot -- no parent, keep running
-		args="--track-mem -R"
-	elif [ $SNAP -eq $NRSNAP ]; then
-		# Last snapshot -- has parent, kill afterwards
-		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem --auto-dedup"
-	else
-		# Other snapshots -- have parent, keep running
-		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem -R --auto-dedup"
-	fi
-
-	if [ $USEPS -eq 1 ]; then
-		${CRIU} page-server -D "${IMGDIR}/$SNAP/" -o ps.log --auto-dedup --port ${PORT} -v4 &
-		PS_PID=$!
-		ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
-	else
-		ps_args=""
-	fi
-
-	${CRIU} dump -D "${IMGDIR}/$SNAP/" -o dump.log -t ${PID} -v4 $args $ps_args || fail "Fail to dump"
-	if [ $USEPS -eq 1 ]; then
-		wait $PS_PID
-	fi
-done
-
-echo "Restoring"
-${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log --auto-dedup -d -v4 || fail "Fail to restore server"
-
-size_last3=$(du -sh -BK dump/3/pages-*.img | grep -Eo '[0-9]+' | head -1)
-size_last2=$(du -sh -BK dump/2/pages-*.img | grep -Eo '[0-9]+' | head -1)
-size_last1=$(du -sh -BK dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
-
-restore_dedup_ok=0
-if [[ $size_last1 -ne 0 || $size_last2 -ne 0 || $size_last3 -ne 0 ]]; then
-	restore_dedup_ok=1
-fi
-
-cd ../zdtm/live/static/
-make mem-touch.stop
-cat mem-touch.out | fgrep PASS || fail "Test failed"
-
-if [ $restore_dedup_ok -ne 0 ]; then
-	fail "Dedup test failed"
-fi
-
-echo "Test PASSED"
diff --git a/test/mem-snap/run-snap-dedup.sh b/test/mem-snap/run-snap-dedup.sh
deleted file mode 100755
index 762e202..0000000
--- a/test/mem-snap/run-snap-dedup.sh
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/bin/bash
-
-source ../env.sh || exit 1
-
-USEPS=0
-
-if [ "$1" = "-s" ]; then
-	echo "Will test via page-server"
-	USEPS=1
-	shift
-fi
-
-NRSNAP=${1:-3}
-SPAUSE=${2:-4}
-PORT=12345
-
-function fail {
-	echo "$@"
-	exit 1
-}
-set -x
-
-IMGDIR="dump/"
-
-rm -rf "$IMGDIR"
-mkdir "$IMGDIR"
-
-echo "Launching test"
-cd ../zdtm/live/static/
-make cleanout
-make mem-touch
-make mem-touch.pid || fail "Can't start test"
-PID=$(cat mem-touch.pid)
-kill -0 $PID || fail "Test didn't start"
-cd -
-
-echo "Making $NRSNAP snapshots"
-
-for SNAP in $(seq 1 $NRSNAP); do
-	sleep $SPAUSE
-	mkdir "$IMGDIR/$SNAP/"
-	if [ $SNAP -eq 1 ] ; then
-		# First snapshot -- no parent, keep running
-		args="--track-mem -R"
-	elif [ $SNAP -eq $NRSNAP ]; then
-		# Last snapshot -- has parent, kill afterwards
-		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem"
-	else
-		# Other snapshots -- have parent, keep running
-		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem -R"
-	fi
-
-	if [ $USEPS -eq 1 ]; then
-		${CRIU} page-server -D "${IMGDIR}/$SNAP/" -o ps.log --port ${PORT} -v4 &
-		PS_PID=$!
-		ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
-	else
-		ps_args=""
-	fi
-
-	${CRIU} dump -D "${IMGDIR}/$SNAP/" -o dump.log -t ${PID} -v4 $args $ps_args || fail "Fail to dump"
-	if [ $USEPS -eq 1 ]; then
-		wait $PS_PID
-	fi
-done
-
-echo "Dedup test"
-
-size_first_2=$(du -sh -BK  dump/2/pages-*.img | grep -Eo '[0-9]+' | head -1)
-size_first_1=$(du -sh -BK  dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
-
-${CRIU} dedup -D "${IMGDIR}/$NRSNAP/"
-
-size_last_2=$(du -sh -BK dump/2/pages-*.img | grep -Eo '[0-9]+' | head -1)
-size_last_1=$(du -sh -BK dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
-
-dedup_ok_2=1
-dedup_ok_1=1
-
-if [ $size_first_2 -gt $size_last_2 ]; then
-	dedup_ok_2=0
-fi
-
-if [ $size_first_1 -gt $size_last_1 ]; then
-	dedup_ok_1=0
-fi
-
-echo "Restoring"
-${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log -d -v4 || fail "Fail to restore server"
-
-cd ../zdtm/live/static/
-make mem-touch.stop
-cat mem-touch.out | fgrep PASS || fail "Test failed"
-
-if [[ $dedup_ok_2 -ne 0 || $dedup_ok_1 -ne 0 ]]; then
-	fail "Dedup test failed"
-fi
-
-echo "Test PASSED"
diff --git a/test/mem-snap/run-snap-maps04.sh b/test/mem-snap/run-snap-maps04.sh
deleted file mode 100755
index 5bd75f3..0000000
--- a/test/mem-snap/run-snap-maps04.sh
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/bash
-
-source ../env.sh || exit 1
-
-USEPS=0
-
-if [ "$1" = "-s" ]; then
-	echo "Will test via page-server"
-	USEPS=1
-	shift
-fi
-
-NRSNAP=1
-SPAUSE=${2:-4}
-PORT=12345
-
-function fail {
-	echo "$@"
-	exit 1
-}
-set -x
-
-IMGDIR="dump"
-CURDIR=${pwd}
-if ! mount | fgrep "$CURDIR/$IMGDIR" ; then
-	rm -rf "$IMGDIR"
-	mkdir "$IMGDIR"
-
-	mount -t tmpfs -o size=1500M,nr_inodes=10k,mode=700 tmpfs $IMGDIR
-fi
-rm -rf "$IMGDIR/*"
-
-echo "Launching test"
-make -C ../zdtm/live/static/ cleanout
-make -C ../zdtm/live/static/ maps04
-make -C ../zdtm/live/static/ maps04.pid || fail "Can't start test"
-PID=$(cat ../zdtm/live/static/maps04.pid)
-kill -0 $PID || fail "Test haven't started"
-
-mkdir "$IMGDIR/$NRSNAP/"
-
-if [ $USEPS -eq 1 ] ; then
-	${CRIU} page-server -D "${IMGDIR}/$NRSNAP/" -o ps.log --port ${PORT} -d -v4 #&
-	PS_PID=$!
-	ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
-else
-	ps_args=""
-fi
-
-${CRIU} dump -D "${IMGDIR}/$NRSNAP/" -o dump.log -t ${PID} -v4 $ps_args || fail "Fail to dump"
-if [ $USEPS -eq 1 ] ; then
-	wait $PS_PID
-fi
-
-echo "Restoring"
-${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log --auto-dedup -d -v4 || fail "Fail to restore"
-
-make -C ../zdtm/live/static/ maps04.stop
-sleep 1
-
-cat "../zdtm/live/static/maps04.out" | fgrep PASS || fail "Test failed"
-
-size=$(du -sh -BK  dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
-if [ $size -ne 0 ] ; then
-	fail "Size not null"
-fi
-
-echo "Test PASSED"
diff --git a/test/mem-snap/run-snap.sh b/test/mem-snap/run-snap.sh
deleted file mode 100755
index 38496a2..0000000
--- a/test/mem-snap/run-snap.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/bin/bash
-
-source ../env.sh || exit 1
-
-USEPS=0
-
-if [ "$1" = "-s" ]; then
-	echo "Will test via page-server"
-	USEPS=1
-	shift
-fi
-
-NRSNAP=${1:-3}
-SPAUSE=${2:-4}
-PORT=12345
-
-function fail {
-	echo "$@"
-	exit 1
-}
-set -x
-
-IMGDIR="dump/"
-
-rm -rf "$IMGDIR"
-mkdir "$IMGDIR"
-
-echo "Launching test"
-cd ../zdtm/live/static/
-make cleanout
-make mem-touch
-make mem-touch.pid || fail "Can't start test"
-PID=$(cat mem-touch.pid)
-kill -0 $PID || fail "Test didn't start"
-cd -
-
-echo "Making $NRSNAP snapshots"
-
-for SNAP in $(seq 1 $NRSNAP); do
-	sleep $SPAUSE
-	mkdir "$IMGDIR/$SNAP/"
-	if [ $SNAP -eq 1 ] ; then
-		# First snapshot -- no parent, keep running
-		args="--track-mem -R"
-	elif [ $SNAP -eq $NRSNAP ]; then
-		# Last snapshot -- has parent, kill afterwards
-		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem"
-	else
-		# Other snapshots -- have parent, keep running
-		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem -R"
-	fi
-
-	if [ $USEPS -eq 1 ]; then
-		${CRIU} page-server -D "${IMGDIR}/$SNAP/" -o ps.log --port ${PORT} -v4 &
-		PS_PID=$!
-		ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
-	else
-		ps_args=""
-	fi
-
-	${CRIU} dump -D "${IMGDIR}/$SNAP/" -o dump.log -t ${PID} -v4 $args $ps_args || fail "Fail to dump"
-	if [ $USEPS -eq 1 ]; then
-		wait $PS_PID
-	fi
-done
-
-echo "Restoring"
-${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log -d -v4 || fail "Fail to restore server"
-
-cd ../zdtm/live/static/
-make mem-touch.stop
-cat mem-touch.out | fgrep PASS || fail "Test failed"
-
-echo "Test PASSED"
diff --git a/test/mem-snap/run.sh b/test/mem-snap/run.sh
deleted file mode 100755
index b3995ec..0000000
--- a/test/mem-snap/run.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-# Don't execute tests, which use maps04, they are executed by zdtm
-
-set -e
-
-#./run-predump-2.sh
-./run-predump.sh
-./run-snap-auto-dedup.sh
-./run-snap-dedup-on-restore.sh
-./run-snap-dedup.sh
-#./run-snap-maps04.sh
-./run-snap.sh
diff --git a/test/mounts/ext/Makefile b/test/mounts/ext/Makefile
deleted file mode 100644
index 282fba0..0000000
--- a/test/mounts/ext/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-all: ext-mount.so ns_init
-
-ext-mount.so: ext-mount.c
-	gcc -g -Werror -Wall -shared -nostartfiles ext-mount.c -o ext-mount.so -iquote ../../../include -fPIC
-
-ns_init: ns_init.o
-	gcc -static $< -o $@
-
-ns_init.o: ns_init.c
-	gcc -c $< -o $@
-
-run: all
-	./run.sh
diff --git a/test/mounts/ext/ext-mount.c b/test/mounts/ext/ext-mount.c
deleted file mode 100644
index e5e974b..0000000
--- a/test/mounts/ext/ext-mount.c
+++ /dev/null
@@ -1,101 +0,0 @@
-#include <sys/mount.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "criu-plugin.h"
-#include "criu-log.h"
-
-#define IMG_NAME	"ext-mount-test-%d.img"
-
-extern cr_plugin_init_t cr_plugin_init;
-extern cr_plugin_dump_ext_mount_t cr_plugin_dump_ext_mount;
-extern cr_plugin_restore_ext_mount_t cr_plugin_restore_ext_mount;
-
-int cr_plugin_init(void)
-{
-	pr_info("Initialized ext mount c/r\n");
-	return 0;
-}
-
-int cr_plugin_dump_ext_mount(char *mountpoint, int id)
-{
-	char *aux, *dst;
-	int fd;
-	char img[64];
-
-	pr_info("Check for ext mount %s being mine\n", mountpoint);
-	aux = strrchr(mountpoint, '/');
-	if (!aux) {
-		pr_err("Bad path provided\n");
-		return -ENOTSUP;
-	}
-
-	dst = getenv("EMP_MOUNTPOINT");
-	if (!dst) {
-		pr_err("No EMP_MOUNTPOINT env\n");
-		return -1;
-	}
-
-	if (strcmp(aux + 1, dst)) {
-		pr_info("Not mine\n");
-		return -ENOTSUP;
-	}
-
-	pr_info("Dumping my mount %d\n", id);
-	sprintf(img, IMG_NAME, id);
-	fd = openat(criu_get_image_dir(), img,
-			O_RDWR | O_CREAT | O_TRUNC, 0600);
-	if (fd < 0) {
-		pr_perror("Can't open image");
-		return -1;
-	}
-
-	close(fd);
-	return 0;
-}
-
-int cr_plugin_restore_ext_mount(int id, char *mountpoint, char *old_root, int *is_file)
-{
-	int fd;
-	char img[64], src[256], *src_file;
-
-	pr_info("Restoring my mount %d?\n", id);
-	sprintf(img, IMG_NAME, id);
-	fd = openat(criu_get_image_dir(), img, O_RDONLY);
-	if (fd < 0) {
-		if (errno == ENOENT)
-			return -ENOTSUP;
-		pr_perror("Can't open my image");
-		return -1;
-	}
-	close(fd);
-
-	src_file = getenv("EMP_ROOT_P");
-	if (!src_file) {
-		pr_err("Can't get EMP_ROOT_P env\n");
-		return -1;
-	}
-
-	if (creat(mountpoint, 0600) < 0) {
-		if (errno != EEXIST) {
-			pr_perror("Can't make mountpoint");
-			return -1;
-		}
-	}
-
-	if (is_file)
-		*is_file = 1;
-
-	sprintf(src, "/%s/%s", old_root, src_file);
-	pr_info("Mount %s -> %s\n", src, mountpoint);
-	if (mount(src, mountpoint, NULL, MS_BIND, NULL) < 0) {
-		pr_perror("Can't bind mount");
-		return -1;
-	}
-
-	return 0;
-}
diff --git a/test/mounts/ext/ns_init.c b/test/mounts/ext/ns_init.c
deleted file mode 100644
index e85bf9d..0000000
--- a/test/mounts/ext/ns_init.c
+++ /dev/null
@@ -1,143 +0,0 @@
-#define _GNU_SOURCE
-#include <sched.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/mount.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <string.h>
-
-static void sigh(int sig)
-{
-}
-
-int main(int argc, char **argv)
-{
-	int start[2];
-	char res;
-	pid_t pid;
-
-	/*
-	 * Usage:
-	 * run <pidfile> <root> <log-file-name> <file-to-check> <contents-to-check>
-	 */
-
-	if (getpid() == 1) {
-		int fd;
-		struct sigaction sa = {};
-		sigset_t mask;
-
-		if (setsid() == -1) {
-			fprintf(stderr, "setsid: %m\n");
-			return 1;
-		}
-
-		sa.sa_handler = sigh;
-		sigaction(SIGTERM, &sa, NULL);
-
-		if (chdir(argv[2]))
-			return 1;
-
-		fd = open(argv[3], O_WRONLY|O_CREAT|O_TRUNC|O_APPEND, 0600);
-		if (fd < 0)
-			return 1;
-
-		dup2(fd, 1);
-		dup2(fd, 2);
-		close(fd);
-		close(0);
-
-		if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
-			fprintf(stderr, "mount(/, S_REC | MS_PRIVATE)): %m");
-			return 1;
-		}
-
-		mkdir("oldm");
-		if (pivot_root(".", "./oldm") < 0)
-			return 1;
-
-		umount2("/oldm", MNT_DETACH);
-
-		mkdir("/proc");
-		if (mount("zdtm_proc", "/proc", "proc", 0, NULL)) {
-			fprintf(stderr, "mount(/proc): %m");
-			return 1;
-		}
-
-		sigemptyset(&mask);
-		sigaddset(&mask, SIGTERM);
-		sigprocmask(SIG_BLOCK, &mask, NULL);
-
-		fd = atoi(argv[1]);
-		write(fd, "!", 1);
-		close(fd);
-
-		sigemptyset(&mask);
-		sigsuspend(&mask);
-
-		printf("Woken UP\n");
-		printf("Reading %s for [%s]\n", argv[4], argv[5]);
-		{
-			FILE *f;
-			char buf[128];
-
-			f = fopen(argv[4], "r");
-			if (!f)
-				perror("No file with message");
-			else {
-				memset(buf, 0, sizeof(buf));
-				fgets(buf, sizeof(buf), f);
-				fclose(f);
-				printf("Got [%s]\n", buf);
-
-				if (!strcmp(buf, argv[5]))
-					printf("PASS\n");
-			}
-		}
-
-		exit(0);
-	}
-
-	if (unshare(CLONE_NEWNS | CLONE_NEWPID))
-		return 1;
-
-	pipe(start);
-	pid = fork();
-	if (pid == 0) {
-		char *nargv[7], aux[10];
-
-		close(start[0]);
-		sprintf(aux, "%d", start[1]);
-		nargv[0] = argv[0];
-		nargv[1] = aux;
-		nargv[2] = argv[2];
-		nargv[3] = argv[3];
-		nargv[4] = argv[4];
-		nargv[5] = argv[5];
-		nargv[6] = NULL;
-
-		execv(argv[0], nargv);
-		exit(0);
-	}
-
-	close(start[1]);
-	res = 'F';
-	read(start[0], &res, 1);
-	if (res != '!') {
-		printf("Failed to start\n");
-		return 1;
-	}
-
-	printf("Container w/ tests started\n");
-	{
-		FILE *pidf;
-		pidf = fopen(argv[1], "w");
-		fprintf(pidf, "%d", pid);
-		fclose(pidf);
-	}
-
-	return 0;
-}
diff --git a/test/mounts/ext/run.sh b/test/mounts/ext/run.sh
deleted file mode 100755
index ff2a2d8..0000000
--- a/test/mounts/ext/run.sh
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/bin/bash
-
-set -x
-
-function fail {
-	echo $@
-	exit 1
-}
-
-make || fail "Can't compile library or ns init"
-
-criu="../../../criu/criu"
-
-# New root for namespace
-NSROOT="nsroot"
-# External file with contents (exported for plugin.restore)
-EMP_ROOT="external_file"
-export EMP_ROOT_P="$(pwd)/$EMP_ROOT"
-# Internal file as seen from namespace (exported for plugin.dump)
-export EMP_MOUNTPOINT="file"
-# Message in a file to check visibility
-FMESSAGE="tram-pam-pam"
-# Binary of namespace's init
-NS_INIT="ns_init"
-# File with namespace init pid
-PIDF="pidf"
-
-start_ns()
-{
-	#
-	# Prepare the namespace's FS layout
-	#
-	mkdir $NSROOT
-	echo -n "$FMESSAGE" > "$EMP_ROOT"
-	mount --bind "$NSROOT" "$NSROOT"
-	mount --make-private "$NSROOT"
-	touch "$NSROOT/$EMP_MOUNTPOINT"
-	mount --bind "$EMP_ROOT" "$NSROOT/$EMP_MOUNTPOINT" || fail "Can't prepare fs for ns"
-
-	#
-	# Start the namespace's init
-	#
-	cp $NS_INIT "$NSROOT/"
-	"./$NSROOT/$NS_INIT" "$PIDF" "$NSROOT" "log" "$EMP_MOUNTPOINT" "$FMESSAGE" || fail "Can't start namespace"
-	umount "$NSROOT/$EMP_MOUNTPOINT"
-
-	echo "Namespace started, pid $(cat $PIDF)"
-}
-
-stop_ns()
-{
-	#
-	# Kill the init
-	#
-
-	kill -TERM $(cat $PIDF)
-	sleep 2 # Shitty, but...
-	umount $NSROOT
-
-	if [ -z "$1" ]; then
-		rm -f "$NSROOT/log"
-	else
-		mv "$NSROOT/log" "$1"
-	fi
-
-	rm -f "$PIDF" "$EMP_ROOT" "$NSROOT/$NS_INIT" "$NSROOT/log" "$NSROOT/$EMP_MOUNTPOINT"
-	rmdir "$NSROOT/oldm"
-	rmdir "$NSROOT/proc"
-	rmdir "$NSROOT"
-}
-
-DDIR="dump"
-rm -rf $DDIR
-mkdir $DDIR
-
-chk_pass()
-{
-	tail -n1 $1 | fgrep -q "PASS"
-}
-
-#
-# Test 1: handle external mount with plugin
-#
-
-test_plugin()
-{
-	echo "=== Testing how plugin works"
-	mkdir "$DDIR/plugin/"
-	start_ns
-
-	$criu dump    -D "$DDIR/plugin/" -v4 -o "dump.log" --lib=$(pwd) \
-			-t $(cat pidf) || { stop_ns; return 1; }
-
-	$criu restore -D "$DDIR/plugin/" -v4 -o "rstr.log" --lib=$(pwd) \
-			-d --root="$(pwd)/$NSROOT" --pidfile=$PIDF || { stop_ns; return 1; }
-
-	echo "Restored, checking results"
-	mv "$DDIR/plugin/$PIDF" .
-	stop_ns "$DDIR/plugin/ns.log"
-	chk_pass "$DDIR/plugin/ns.log"
-}
-
-test_ext_mount_map()
-{
-	echo "=== Testing how --ext-mount-map works"
-	mkdir "$DDIR/ext_mount_map/"
-	start_ns
-
-	$criu dump    -D "$DDIR/ext_mount_map/" -v4 -o "dump.log" \
-			-t $(cat pidf) --ext-mount-map "/$EMP_MOUNTPOINT:TM" || { stop_ns; return 1; }
-
-	$criu restore -D "$DDIR/ext_mount_map/" -v4 -o "rstr.log" \
-			-d --root="$(pwd)/$NSROOT" --pidfile=$PIDF --ext-mount-map "TM:$EMP_ROOT_P" || { stop_ns; return 1; }
-
-	echo "Restored, checking results"
-	mv "$DDIR/ext_mount_map/$PIDF" .
-	stop_ns "$DDIR/ext_mount_map/ns.log"
-	chk_pass "$DDIR/ext_mount_map/ns.log"
-}
-
-test_plugin || exit 1
-test_ext_mount_map || exit 1
-
-echo "All tests passed"
-exit 0
diff --git a/test/mounts/mounts.py b/test/mounts/mounts.py
deleted file mode 100755
index 7f11d7d..0000000
--- a/test/mounts/mounts.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import os
-import tempfile, random
-
-def mount(src, dst, shared, private, slave):
-	cmd = "mount"
-	if shared:
-		cmd += " --make-shared"
-	if private:
-		cmd += " --make-private"
-	if slave:
-		cmd += " --make-slave"
-	if src:
-		cmd += " --bind '%s' '%s'" % (src, dst)
-	else:
-		cmd += " -t tmpfs none '%s'" % (dst)
-
-	print cmd
-	ret = os.system(cmd)
-	if ret:
-		print "failed"
-
-root = tempfile.mkdtemp(prefix = "root.mount", dir = "/tmp")
-mount(None, root, 1, 0, 0)
-mounts = [root]
-
-for i in xrange(10):
-	dstdir = random.choice(mounts)
-	dst = tempfile.mkdtemp(prefix = "mount", dir = dstdir)
-	src = random.choice(mounts + [None])
-	mount(src, dst, random.randint(0,100) > 50, random.randint(0,100) > 90, random.randint(0,100) > 50)
-	mounts.append(dst)
diff --git a/test/mounts/mounts.sh b/test/mounts/mounts.sh
deleted file mode 100755
index 19116d0..0000000
--- a/test/mounts/mounts.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-[ -z "$INMNTNS" ] && {
-	export INMNTNS=`pwd`
-	export INMNTNS_PID=$$
-	unshare -m -- setsid bash -x "$0" "$@" < /dev/null &> mounts.log &
-	echo $! > mounts.pid
-	while :; do
-		sleep 1
-	done
-}
-
-cd $INMNTNS
-
-mount --make-rprivate /
-
-for i in `cat /proc/self/mounts | awk '{ print $2 }'`; do
-	[ '/' = "$i" ] && continue
-	[ '/proc' = "$i" ] && continue
-	[ '/dev' = "$i" ] && continue
-	echo $i
-	umount -l $i
-done
-
-python mounts.py
-kill $INMNTNS_PID
-while :; do
-	sleep 10
-done
diff --git a/test/mounts/run.sh b/test/mounts/run.sh
deleted file mode 100755
index 23d05e5..0000000
--- a/test/mounts/run.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-
-CRIU=../../criu
-set -x
-
-mkdir -p dump
-
-./mounts.sh
-pid=`cat mounts.pid`
-kill -0 $pid || exit
-
-cat /proc/$pid/mountinfo | sort -k 4
-echo "Suspend server"
-${CRIU} dump -D dump -o dump.log -t $pid -v4 || {
-	cat dump/dump.log | grep Error
-	exit 1
-}
-echo "Resume server"
-${CRIU} restore -d -D dump -o restore.log -v4 || {
-	cat dump/dump.log | grep Error
-	exit 1
-}
-cat /proc/$pid/mountinfo | sort -k 4
-kill $pid
diff --git a/test/others/bers/Makefile b/test/others/bers/Makefile
new file mode 100644
index 0000000..74b6142
--- /dev/null
+++ b/test/others/bers/Makefile
@@ -0,0 +1,47 @@
+ifeq ($(strip $(V)),)
+	E = @echo
+	Q = @
+else
+	E = @\#
+	Q =
+endif
+
+export E Q
+
+ASCIIDOC	:= asciidoc
+A2X		:= a2x
+XMLTO		:= xmlto
+
+SRC		+= bers.txt
+XMLS		:= $(patsubst %.txt,%.xml,$(SRC))
+MANS		:= $(patsubst %.txt,%.8,$(SRC))
+
+%.8: %.txt
+	$(E) "  GEN     " $@
+	$(Q) $(ASCIIDOC) -b docbook -d manpage -o $(patsubst %.8,%.xml,$@) $<
+	$(Q) $(XMLTO) man --skip-validation $(patsubst %.8,%.xml,$@) 2>/dev/null
+
+docs: $(MANS)
+	@true
+
+CFLAGS := -O0 -ggdb3
+LIBS := -lpthread
+
+%.o: %.c
+	$(E) "  CC      " $@
+	$(Q) $(CC) -c -o $@ $(CFLAGS) $^
+
+bers: bers.o
+	$(E) "  LINK    " $@
+	$(Q) $(CC) -o $@ $(CFLAGS) $(LIBS) $^
+
+all: bers
+	@true
+
+clean:
+	$(E) "  CLEAN   "
+	$(Q) rm -f $(XMLS) $(MANS)
+	$(Q) rm -f bers.o
+	$(Q) rm -f bers
+
+.PHONY: all docs clean
diff --git a/test/others/bers/bers.c b/test/others/bers/bers.c
new file mode 100644
index 0000000..208325c
--- /dev/null
+++ b/test/others/bers/bers.c
@@ -0,0 +1,420 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <limits.h>
+#include <stdbool.h>
+
+#include <pthread.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <syscall.h>
+
+#define min(x, y) ({				\
+	typeof(x) _min1 = (x);			\
+	typeof(y) _min2 = (y);			\
+	(void) (&_min1 == &_min2);		\
+	_min1 < _min2 ? _min1 : _min2; })
+
+#define max(x, y) ({				\
+	typeof(x) _max1 = (x);			\
+	typeof(y) _max2 = (y);			\
+	(void) (&_max1 == &_max2);		\
+	_max1 > _max2 ? _max1 : _max2; })
+
+#define MAX_CHUNK		4096
+#define PAGE_SIZE		4096
+
+#define pr_info(fmt, ...)				\
+	printf("%8d: " fmt, sys_gettid(), ##__VA_ARGS__)
+
+#define pr_err(fmt, ...)				\
+	printf("%8d: Error (%s:%d): " fmt, sys_gettid(),\
+		       __FILE__, __LINE__, ##__VA_ARGS__)
+
+#define pr_perror(fmt, ...)				\
+	pr_err(fmt ": %m\n", ##__VA_ARGS__)
+
+#define pr_msg(fmt, ...)				\
+	printf(fmt, ##__VA_ARGS__)
+
+
+#define pr_trace(fmt, ...)				\
+	printf("%8d: %s: " fmt, sys_gettid(), __func__,	\
+		##__VA_ARGS__)
+
+enum {
+	MEM_FILL_MODE_NONE	= 0,
+	MEM_FILL_MODE_ALL	= 1,
+	MEM_FILL_MODE_LIGHT	= 2,
+	MEM_FILL_MODE_DIRTIFY	= 3,
+};
+
+typedef struct {
+	pthread_mutex_t		mutex;
+	pthread_mutexattr_t	mutex_attr;
+
+	size_t			opt_tasks;
+
+	size_t			opt_files;
+	size_t			opt_file_size;
+	int			prev_fd[MAX_CHUNK];
+
+	size_t			opt_mem;
+	size_t			opt_mem_chunks;
+	size_t			opt_mem_chunk_size;
+	int			opt_mem_fill_mode;
+	int			opt_mem_cycle_mode;
+	unsigned int		opt_refresh_time;
+
+	char			*opt_work_dir;
+	int			work_dir_fd;
+	DIR			*work_dir;
+
+	pid_t			err_pid;
+	int			err_no;
+
+	unsigned long		prev_map[MAX_CHUNK];
+} shared_data_t;
+
+static shared_data_t *shared;
+
+static int sys_gettid(void)
+{
+	return syscall(__NR_gettid);
+}
+
+static void dirtify_memory(unsigned long *chunks, size_t nr_chunks,
+			   size_t chunk_size, int mode, const size_t nr_pages)
+{
+	void *page;
+	size_t i;
+
+	pr_trace("filling memory\n");
+	switch (mode) {
+	case MEM_FILL_MODE_LIGHT:
+		*((unsigned long *)chunks[0]) = -1ul;
+		break;
+	case MEM_FILL_MODE_ALL:
+		for (i = 0; i < nr_chunks; i++)
+			memset((void *)chunks[i], (char)i, chunk_size);
+		break;
+	case MEM_FILL_MODE_DIRTIFY:
+		for (i = 0; i < nr_chunks; i++)
+			*((unsigned long *)chunks[i]) = -1ul;
+		break;
+	}
+}
+
+static void dirtify_files(int *fd, size_t nr_files, size_t size)
+{
+	size_t buf[8192];
+	size_t i, j, c;
+
+	/*
+	 * Note we don't write any _sane_ data here, the only
+	 * important thing is I/O activity by self.
+	 */
+
+	for (i = 0; i < nr_files; i++) {
+		size_t c = min(size, sizeof(buf));
+		size_t left = size;
+
+		while (left > 0) {
+			write(fd[i], buf, c);
+			left -= c;
+			c = min(left, sizeof(buf));
+		}
+	}
+}
+
+static int create_files(shared_data_t *shared, int *fd, size_t nr_files)
+{
+	char path[PATH_MAX];
+	size_t i;
+
+	memset(fd, 0xff, sizeof(fd));
+
+	pr_info("\tCreating %lu files\n", shared->opt_files);
+
+	for (i = 0; i < shared->opt_files; i++) {
+		if (shared->prev_fd[i] != -1) {
+			close(shared->prev_fd[i]);
+			shared->prev_fd[i] = -1;
+		}
+		snprintf(path, sizeof(path), "%08d-%04d-temp", sys_gettid(), i);
+		fd[i] = openat(shared->work_dir_fd, path, O_RDWR | O_CREAT | O_TRUNC, 0666);
+		if (fd[i] < 0) {
+			pr_perror("Can't open %s/%s", shared->opt_work_dir, path);
+			shared->err_pid = sys_gettid();
+			shared->err_no = -errno;
+			return -1;
+		}
+		shared->prev_fd[i] = fd[i];
+	}
+
+	return 0;
+}
+
+static void work_on_fork(shared_data_t *shared)
+{
+	const size_t nr_pages = shared->opt_mem_chunk_size / PAGE_SIZE;
+	unsigned long chunks[MAX_CHUNK] = { };
+	int fd[MAX_CHUNK];
+	size_t i;
+	void *mem;
+
+	pr_trace("locking\n");
+	pthread_mutex_lock(&shared->mutex);
+	pr_trace("init\n");
+
+	pr_info("\tCreating %lu mmaps each %lu K\n",
+		shared->opt_mem_chunks, shared->opt_mem_chunk_size >> 10);
+
+	for (i = 0; i < shared->opt_mem_chunks; i++) {
+		if (shared->prev_map[i]) {
+			munmap((void *)shared->prev_map[i], shared->opt_mem_chunk_size);
+			shared->prev_map[i] = 0;
+		}
+
+		/* If we won't change proto here, the kernel might merge close areas */
+		mem = mmap(NULL, shared->opt_mem_chunk_size,
+			   PROT_READ | PROT_WRITE | ((i % 2) ? PROT_EXEC : 0),
+			   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+
+		if (mem != (void *)MAP_FAILED) {
+			shared->prev_map[i] = (unsigned long)mem;
+			chunks[i] = (unsigned long)mem;
+
+			pr_info("\t\tMap at %lx\n",(unsigned long)mem);
+		} else {
+			pr_info("\t\tCan't map\n");
+
+			shared->err_pid	= sys_gettid();
+			shared->err_no	= -errno;
+			exit(1);
+		}
+	}
+
+	if (shared->opt_mem_fill_mode)
+		dirtify_memory(chunks, shared->opt_mem_chunks,
+			       shared->opt_mem_chunk_size,
+			       shared->opt_mem_fill_mode,
+			       nr_pages);
+
+	if (create_files(shared, fd, shared->opt_files))
+		exit(1);
+
+	if (shared->opt_file_size)
+		dirtify_files(fd, shared->opt_files, shared->opt_file_size);
+
+		pr_trace("releasing\n");
+	pthread_mutex_unlock(&shared->mutex);
+
+	while (1) {
+		sleep(shared->opt_refresh_time);
+		if (shared->opt_mem_cycle_mode)
+			dirtify_memory(chunks, shared->opt_mem_chunks,
+				       shared->opt_mem_chunk_size,
+				       shared->opt_mem_cycle_mode,
+				       nr_pages);
+		if (shared->opt_file_size)
+			dirtify_files(fd, shared->opt_files, shared->opt_file_size);
+	}
+}
+
+static int parse_mem_mode(int *mode, char *opt)
+{
+	if (!strcmp(opt, "all")) {
+		*mode = MEM_FILL_MODE_ALL;
+	} else if (!strcmp(opt, "light")) {
+		*mode = MEM_FILL_MODE_LIGHT;
+	} else if (!strcmp(opt, "dirtify")) {
+		*mode = MEM_FILL_MODE_DIRTIFY;
+	} else {
+		pr_err("Unrecognized option %s\n", opt);
+		return -1;
+	}
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	/* a - 97, z - 122, A - 65, 90 */
+	static const char short_opts[] = "t:d:f:m:c:h";
+	static struct option long_opts[] = {
+		{"tasks",	required_argument, 0,	't'},
+		{"dir",		required_argument, 0,	'd'},
+		{"files",	required_argument, 0,	'f'},
+		{"memory",	required_argument, 0,	'm'},
+		{"mem-chunks",	required_argument, 0,	'c'},
+		{"help",	no_argument,       0,	'h'},
+		{"mem-fill",	required_argument, 0,	 10},
+		{"mem-cycle",	required_argument, 0,	 11},
+		{"refresh",	required_argument, 0,	 12},
+		{"file-size",	required_argument, 0,	 13},
+		{ },
+	};
+
+	char workdir[PATH_MAX];
+	int opt, idx, pidfd;
+	char pidbuf[32];
+	int status;
+	pid_t pid;
+	size_t i;
+
+	shared = (void *)mmap(NULL, sizeof(*shared), PROT_READ | PROT_WRITE,
+			      MAP_ANONYMOUS | MAP_SHARED, -1, 0);
+	if ((void *)shared == MAP_FAILED) {
+		pr_err("Failed to setup shared data\n");
+		exit(1);
+	}
+
+	pthread_mutexattr_init(&shared->mutex_attr);
+	pthread_mutexattr_setpshared(&shared->mutex_attr, PTHREAD_PROCESS_SHARED);
+	pthread_mutex_init(&shared->mutex, &shared->mutex_attr);
+
+	/*
+	 * Default options.
+	 */
+	shared->opt_mem_chunks = 1;
+	shared->opt_refresh_time = 1;
+	shared->opt_tasks = 1;
+	shared->opt_mem = 1 << 20ul;
+	memset(shared->prev_fd, 0xff, sizeof(shared->prev_fd));
+
+	while (1) {
+		idx = -1;
+		opt = getopt_long(argc, argv, short_opts, long_opts, &idx);
+		if (opt == -1)
+			break;
+
+		switch(opt) {
+		case 't':
+			shared->opt_tasks = (size_t)atol(optarg);
+			break;
+		case 'f':
+			shared->opt_files = (size_t)atol(optarg);
+			break;
+		case 'm':
+			/* In megabytes */
+			shared->opt_mem = (size_t)atol(optarg) << 20ul;
+			break;
+		case 'c':
+			shared->opt_mem_chunks = (size_t)atol(optarg);
+			break;
+		case 'd':
+			shared->opt_work_dir = optarg;
+			break;
+		case 'h':
+			goto usage;
+			break;
+		case 10:
+			if (parse_mem_mode(&shared->opt_mem_fill_mode, optarg))
+				goto usage;
+		case 11:
+			if (parse_mem_mode(&shared->opt_mem_cycle_mode, optarg))
+				goto usage;
+			break;
+		case 12:
+			shared->opt_refresh_time = (unsigned int)atoi(optarg);
+			break;
+		case 13:
+			shared->opt_file_size = (size_t)atol(optarg);
+		}
+	}
+
+	if (!shared->opt_work_dir) {
+		shared->opt_work_dir = getcwd(workdir, sizeof(workdir));
+		if (!shared->opt_work_dir)	{
+			pr_perror("Can't fetch current working dir");
+			exit(1);
+		}
+		shared->opt_work_dir = workdir;
+	}
+
+	if (shared->opt_mem_chunks > MAX_CHUNK)
+		shared->opt_mem_chunks = MAX_CHUNK;
+
+	if (shared->opt_files > MAX_CHUNK)
+		shared->opt_files = MAX_CHUNK;
+
+	shared->work_dir = opendir(shared->opt_work_dir);
+	if (!shared->work_dir) {
+		pr_perror("Can't open working dir `%s'",
+			  shared->opt_work_dir);
+		exit(1);
+	}
+	shared->work_dir_fd = dirfd(shared->work_dir);
+
+	shared->opt_mem_chunk_size = shared->opt_mem / shared->opt_mem_chunks;
+
+	if (shared->opt_mem_chunk_size &&
+	    shared->opt_mem_chunk_size < PAGE_SIZE) {
+		pr_err("Memory chunk size is too small, provide at least %lu M of memory\n",
+		       (shared->opt_mem_chunks * PAGE_SIZE) >> 20ul);
+		exit(1);
+	}
+
+	for (i = 0; i < shared->opt_tasks; i++) {
+		if (shared->err_no)
+			goto err_child;
+
+		pid = fork();
+		if (pid < 0) {
+			printf("Can't create fork: %m\n");
+			exit(1);
+		} else if (pid == 0) {
+			work_on_fork(shared);
+		}
+	}
+
+	/*
+	 * Once everything is done and we're in cycle,
+	 * create pidfile and go to sleep...
+	 */
+	pid = sys_gettid();
+	pidfd = openat(shared->work_dir_fd, "bers.pid", O_RDWR | O_CREAT | O_TRUNC, 0666);
+	if (pidfd < 0) {
+		pr_perror("Can't open pidfile");
+		exit(1);
+	}
+	snprintf(pidbuf, sizeof(pidbuf), "%d", sys_gettid());
+	write(pidfd, pidbuf, strlen(pidbuf));
+	close(pidfd);
+	pidfd = -1;
+
+	/*
+	 * Endless!
+	 */
+	while (!shared->err_no)
+		sleep(1);
+
+err_child:
+	pr_err("Child %d exited with %d\n",
+	       shared->err_pid, shared->err_no);
+	return shared->err_no;
+
+usage:
+	pr_msg("bers [options]\n");
+	pr_msg("    -t|--tasks <num>         create <num> of tasks\n");
+	pr_msg("    -d|--dir <dir>           use directory <dir> for temporary files\n");
+	pr_msg("    -f|--files <num>         create <num> files for each task\n");
+	pr_msg("    -m|--memory <num>        allocate <num> megabytes for each task\n");
+	pr_msg("    --memory-chunks <num>    split memory to <num> equal parts\n");
+	pr_msg("    --mem-fill <mode>        fill memory with data dependin on <mode>:\n");
+	pr_msg("                all          fill every byte of memory\n");
+	pr_msg("                light        fill first bytes of every page\n");
+	pr_msg("                dirtify      fill every page\n");
+	pr_msg("    --mem-cycle <mode>       same as --mem-fill but for cycling\n");
+	pr_msg("    --refresh <second>       refresh loading of every task each <second>\n");
+	pr_msg("    --file-size <bytes>      write <bytes> of data into each file on every refresh cycle\n");
+
+	return 1;
+}
diff --git a/test/others/bers/bers.txt b/test/others/bers/bers.txt
new file mode 100644
index 0000000..17c0c08
--- /dev/null
+++ b/test/others/bers/bers.txt
@@ -0,0 +1,74 @@
+bers(8)
+=======
+:doctype:       manpage
+:man source:    bers
+:man version:   0.0.1
+:man manual:    bers manual
+
+NAME
+----
+bers - go berserk and eat computer resources
+
+SYNOPSIS
+--------
+*bers* ['options']
+
+DESCRIPTION
+-----------
+*bers* is a command line utility aimed to eat resources of the computer it runs on.
+Idea behind is to create a number of tasks which would trash computer resources
+eating cpu and i/o time.
+
+OPTIONS
+-------
+*-t*, *--tasks* 'num'::
+	Create 'num' number of forks.
+
+*-d*, *--dir* 'dir'::
+	Path to 'dir' directory where temporary files will be created to load
+	I/O subsystem.
+
+*-f*, *--files* 'num'::
+	Create 'num' files in each task.
+
+*-m*, *--memory* 'num'::
+	Allocate 'num' megabytes of memory for every task.
+
+*--mem-chunks* 'num'::
+	Allocate memory for each task not as one slab but split
+	it into 'num' equal parts.
+
+*--mem-fill* 'mode'::
+	Touch (write) into allocated memory once task is created. The
+	'mode' might be one of the following: 'all' -- write every
+	single byte of the memory, 'light' -- write into first bytes
+	of first page of the allocated memory chunk, 'dirtify' -- write
+	into every page of every allocated chunk.
+
+*--mem-cycle* 'mode'::
+	Same as *--mem-fill*, but 'mode' taken into account while
+	task is cycling. By default each cycle initiated per one second.
+
+*--refresh* 'second'::
+	Refresh load state of every task each 'second'. By refsresh
+	here means to dirtify memory and file contents.
+
+*--file-size* 'bytes'::
+	Write 'bytes' of data into each file on every refresh cycle.
+
+EXAMPLE
+-------
+
+bers -d test/bers/dump -t 256 -m 54 -c 4 -f 200 --mem-fill dirtify --mem-cycle dirtify
+
+We generate 256 tasks wit each allocating 54 megabytes of memory splitted
+equally into 4 memory areas. Each task opens 200 files. On creation and
+cycling we touch every page of every memory area.
+
+AUTHOR
+------
+OpenVZ team.
+
+COPYRIGHT
+---------
+Copyright \(C) 2014, Parallels Inc.
diff --git a/test/others/ext-links/Makefile b/test/others/ext-links/Makefile
new file mode 100644
index 0000000..236a97d
--- /dev/null
+++ b/test/others/ext-links/Makefile
@@ -0,0 +1,4 @@
+all: mvlink.so
+
+mvlink.so: mvlink.c
+	gcc -g -Werror -Wall -shared -nostartfiles mvlink.c -o mvlink.so -iquote ../../../criu/include -fPIC
diff --git a/test/others/ext-links/addmv.sh b/test/others/ext-links/addmv.sh
new file mode 100755
index 0000000..0ccc971
--- /dev/null
+++ b/test/others/ext-links/addmv.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+# $1 -- link name
+# $2 -- file with namespace pid
+if [ "$CRTOOLS_SCRIPT_ACTION" == "setup-namespaces" ]; then
+	$(dirname $0)/addmv_raw.sh $1 $(cat $2)
+else
+	exit 0
+fi
diff --git a/test/others/ext-links/addmv_raw.sh b/test/others/ext-links/addmv_raw.sh
new file mode 100755
index 0000000..224f243
--- /dev/null
+++ b/test/others/ext-links/addmv_raw.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+# $1 -- link name
+# $2 -- pid of task in namespace
+set -x
+$ip link add link eth0 name $1 type macvlan || exit 1
+$ip link set $1 netns $2
diff --git a/test/others/ext-links/mvlink.c b/test/others/ext-links/mvlink.c
new file mode 100644
index 0000000..a1c764d
--- /dev/null
+++ b/test/others/ext-links/mvlink.c
@@ -0,0 +1,28 @@
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "criu-plugin.h"
+#include "criu-log.h"
+
+extern cr_plugin_init_t cr_plugin_init;
+extern cr_plugin_dump_ext_link_t cr_plugin_dump_ext_link;
+
+int cr_plugin_init(void)
+{
+	pr_info("Initialized macvlan dumper\n");
+	return 0;
+}
+
+int cr_plugin_dump_ext_link(int index, int type, char *kind)
+{
+	if (strcmp(kind, "macvlan"))
+		return -ENOTSUP;
+	else {
+		pr_info("Dump %d macvlan\n", index);
+		return 0;
+	}
+}
diff --git a/test/others/ext-links/run.sh b/test/others/ext-links/run.sh
new file mode 100755
index 0000000..82fa393
--- /dev/null
+++ b/test/others/ext-links/run.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+ip=${CR_IP_TOOL:-ip}
+mvln="mv0"
+finf="finish"
+outf="ns_output"
+pidf="ns_pid"
+criu="../../../criu/criu"
+
+export ip
+export mvln
+export finf
+export outf
+export pidf
+
+function fail {
+	$ip link del $mvln
+	touch $finf
+	echo $@
+	exit 1
+}
+
+# Build the mvlink plugin
+make
+
+set -x
+
+rm -f "$finf" "$outf" "$pidf"
+rm -rf "dump"
+
+# Unshare netns. The run_ns will exit once ns is spawned.
+unshare --net ./run_ns.sh
+nspid=$(cat $pidf)
+ps $nspid
+
+# Create and push macvlan device into it. CRIU doesn't support
+# macvlans treating them as external devices.
+./addmv_raw.sh $mvln $nspid || fail "Can't setup namespace"
+
+# Dump
+sleep 1
+mkdir dump
+$criu dump -t $nspid -D dump/ -o dump.log -v4 --lib $(pwd) || fail "Can't dump namespace"
+
+# Restore
+# Ask for the pid (shouldn't change, so just as an example), ask to call
+# script that will put macvlan device back into namespace
+sleep 1
+rm -f $pidf
+$criu restore -D dump/ -o restore.log -v4 --pidfile $(pwd)/$pidf --action-script "$(pwd)/addmv.sh $mvln $(pwd)/$pidf" -d || fail "Can't restore namespaces"
+
+# Finish and check results
+touch $finf
+set +x
+while ! egrep 'PASS|FAIL' $outf; do
+	echo "Waiting"
+	sleep 1
+done
diff --git a/test/others/ext-links/run_ns.sh b/test/others/ext-links/run_ns.sh
new file mode 100755
index 0000000..878f038
--- /dev/null
+++ b/test/others/ext-links/run_ns.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+set -x
+echo "NS: $$" >> $outf
+echo "Links before:" >> $outf
+$ip link list >> $outf 2>&1
+# Detach from session, terminal and parent
+setsid ./run_wait.sh < /dev/null >> $outf 2>&1 &
+# Keep pid for future reference :)
+echo "$!" > $pidf
+exit 0
diff --git a/test/others/ext-links/run_wait.sh b/test/others/ext-links/run_wait.sh
new file mode 100755
index 0000000..d600e37
--- /dev/null
+++ b/test/others/ext-links/run_wait.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+echo "Wait: $$"
+while [ ! -e "$finf" ]; do
+	echo "WAIT ($$)"
+	sleep 1;
+done
+
+echo "Links after:"
+$ip link list
+
+# The mvln device (exported from run.sh) should exits in
+# namespace after we get restored
+echo "Check for $mvln:"
+$ip link list $mvln && echo "PASS" || echo "FAIL"
diff --git a/test/others/ext-tty/run.py b/test/others/ext-tty/run.py
new file mode 100755
index 0000000..22288e3
--- /dev/null
+++ b/test/others/ext-tty/run.py
@@ -0,0 +1,36 @@
+import subprocess
+import pty
+import os, sys, time
+
+master, slave = pty.openpty()
+
+p = subprocess.Popen(["setsid", "--ctty", "sleep", "10000"],
+			stdin = slave, stdout = slave, stderr = slave, close_fds = True)
+st = os.stat("/proc/self/fd/%d" % slave)
+ttyid = "tty[%x:%x]" % (st.st_rdev, st.st_dev)
+os.close(slave)
+time.sleep(1)
+
+ret = subprocess.Popen(["../../../criu/criu", "dump", "-t", str(p.pid), "-v4", "--external", ttyid]).wait()
+if ret:
+	sys.exit(ret)
+p.wait()
+
+new_master, slave = pty.openpty() # get another pty pair
+os.close(master)
+
+ttyid = "fd[%d]:tty[%x:%x]" % (slave, st.st_rdev, st.st_dev)
+
+ret = subprocess.Popen(["../../../criu/criu", "restore", "-v4", "--inherit-fd", ttyid, "--restore-sibling", "--restore-detach"]).wait()
+if ret:
+	sys.exit(ret)
+os.close(slave)
+os.waitpid(-1, os.WNOHANG) # is the process alive
+
+os.close(new_master)
+_, status = os.wait()
+if not os.WIFSIGNALED(status) or not os.WTERMSIG(status):
+	print status
+	sys.exit(1)
+
+print "PASS"
diff --git a/test/others/fault-injection/Makefile b/test/others/fault-injection/Makefile
new file mode 100644
index 0000000..23257eb
--- /dev/null
+++ b/test/others/fault-injection/Makefile
@@ -0,0 +1,2 @@
+all:
+	stap -g -d ../../../criu/criu parasite.stp $$RANDOM -c 'bash -x ../zdtm.sh -d -x socket-tcp'
diff --git a/test/others/fault-injection/parasite.stp b/test/others/fault-injection/parasite.stp
new file mode 100644
index 0000000..c1b0818
--- /dev/null
+++ b/test/others/fault-injection/parasite.stp
@@ -0,0 +1,44 @@
+global i, n, fini_cmd = -1, last_cmd
+
+probe process("../../criu/criu").begin
+{
+	i = 0;
+	/* randint() returns numbers multiple of 5 */
+	n = randint(20 * 5) / 5
+	printf("The %d command will be replaced on -1\n", n);
+}
+
+probe process("../../criu/criu").function("__parasite_execute_daemon")
+{
+	printf("%s\n", $$parms);
+	last_cmd = $cmd;
+	if (++i > n) {
+		printf("Send invalid command to parasite\n");
+		$cmd = -1;
+	}
+}
+
+probe process("../../criu/criu").function("__parasite_execute_daemon").return
+{
+	printf("%d\n", $return);
+}
+
+probe process("../../criu/criu").function("main").return
+{
+	printf("CRIU exits with code %d\n", $return);
+	if  ( i > n) {
+		if ($return)
+			$return = 0;
+		else {
+			printf("CRIU exited with zero code\n");
+			if (fini_cmd < 0 || fini_cmd == last_cmd) {
+				printf("%d looks like FINI command\n", n);
+				fini_cmd = last_cmd
+			} else {
+				printf("This is the second FINI command %d (%d)",
+								n, fini_cmd);
+				$return = 1;
+			}
+		}
+	}
+}
diff --git a/test/others/libcriu/.gitignore b/test/others/libcriu/.gitignore
new file mode 100644
index 0000000..6424681
--- /dev/null
+++ b/test/others/libcriu/.gitignore
@@ -0,0 +1,6 @@
+test_errno
+test_iters
+test_notify
+test_self
+test_sub
+wdir
diff --git a/test/others/libcriu/Makefile b/test/others/libcriu/Makefile
new file mode 100644
index 0000000..d828f7e
--- /dev/null
+++ b/test/others/libcriu/Makefile
@@ -0,0 +1,26 @@
+TESTS += test_sub 
+TESTS += test_self
+TESTS += test_notify
+TESTS += test_iters
+TESTS += test_errno
+
+all: $(TESTS)
+
+run: all
+	./run.sh
+
+define genb
+$(1): $(1).o lib.o
+	gcc $$^ -L ../../../../criu/lib/c/ -L ../../../../criu/images/ -lcriu -o $$@
+endef
+
+$(foreach t, $(TESTS), $(eval $(call genb, $(t))))
+
+%.o: %.c
+	gcc -c $^ -I../../../../criu/lib/c/ -I../../../../criu/images/ -o $@ -Werror
+
+clean:
+	rm -rf $(TESTS) $(TESTS:%=%.o) lib.o
+
+.PHONY: clean
+.PHONY: all
diff --git a/test/others/libcriu/lib.c b/test/others/libcriu/lib.c
new file mode 100644
index 0000000..33aa409
--- /dev/null
+++ b/test/others/libcriu/lib.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+void what_err_ret_mean(int ret)
+{
+	/* NOTE: errno is set by libcriu */
+	switch (ret) {
+	case -EBADE:
+		perror("RPC has returned fail");
+		break;
+	case -ECONNREFUSED:
+		perror("Unable to connect to CRIU");
+		break;
+	case -ECOMM:
+		perror("Unable to send/recv msg to/from CRIU");
+		break;
+	case -EINVAL:
+		perror("CRIU doesn't support this type of request."
+		       "You should probably update CRIU");
+		break;
+	case -EBADMSG:
+		perror("Unexpected response from CRIU."
+		       "You should probably update CRIU");
+		break;
+	default:
+		perror("Unknown error type code."
+		       "You should probably update CRIU");
+	}
+}
+
+int chk_exit(int status, int want)
+{
+	if (WIFEXITED(status)) {
+		if (WEXITSTATUS(status) == want)
+			return 0;
+
+		printf("   `- FAIL (exit %d)\n", WEXITSTATUS(status));
+	} else if (WIFSIGNALED(status))
+		printf("   `- FAIL (die %d)\n", WTERMSIG(status));
+	else
+		printf("   `- FAIL (%#x)\n", status);
+
+	return 1;
+}
+
+
diff --git a/test/others/libcriu/lib.h b/test/others/libcriu/lib.h
new file mode 100644
index 0000000..67b784b
--- /dev/null
+++ b/test/others/libcriu/lib.h
@@ -0,0 +1,2 @@
+void what_err_ret_mean(int ret);
+int chk_exit(int status, int want);
diff --git a/test/others/libcriu/run.sh b/test/others/libcriu/run.sh
new file mode 100755
index 0000000..f7b3b68
--- /dev/null
+++ b/test/others/libcriu/run.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+set -x
+source ../../env.sh || exit 1
+
+echo "== Clean"
+make clean
+rm -rf wdir
+rm -f ./libcriu.so.1
+
+echo "== Prepare"
+mkdir -p wdir/i/
+
+echo "== Run tests"
+ln -s ../../../../criu/lib/c/libcriu.so libcriu.so.1
+export LD_LIBRARY_PATH=.
+export PATH="`dirname ${BASH_SOURCE[0]}`/../../:$PATH"
+
+RESULT=0
+
+function run_test {
+	echo "== Build $1"
+	if ! make $1; then
+		echo "FAIL build $1"
+		RESULT=1;
+	else
+		echo "== Test $1"
+		mkdir wdir/i/$1/
+		if ! setsid ./$1 ${CRIU} wdir/i/$1/ < /dev/null &>> wdir/i/$1/test.log; then
+			echo "$1: FAIL"
+			RESULT=1
+		fi
+	fi
+}
+
+run_test test_sub
+run_test test_self
+run_test test_notify
+run_test test_iters
+run_test test_errno
+
+echo "== Tests done"
+unlink libcriu.so.1
+[ $RESULT -eq 0 ] && echo "Success" || echo "FAIL"
+exit $RESULT
diff --git a/test/others/libcriu/test_errno.c b/test/others/libcriu/test_errno.c
new file mode 100644
index 0000000..e091443
--- /dev/null
+++ b/test/others/libcriu/test_errno.c
@@ -0,0 +1,154 @@
+#include "criu.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+
+#define PID_MAX "/proc/sys/kernel/pid_max"
+
+static int dir_fd;
+static char *service;
+
+static int init(char *argv[])
+{
+	service = argv[1];
+
+	dir_fd = open(argv[2], O_DIRECTORY);
+	if (dir_fd < 0) {
+		perror("Can't open images dir");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void get_base_req(void)
+{
+	criu_init_opts();
+	criu_set_service_binary(service);
+	criu_set_images_dir_fd(dir_fd);
+	criu_set_log_level(4);
+}
+
+static int check_resp(int ret, int expected_ret, int err, int expected_err)
+{
+	if (ret != expected_ret) {
+		fprintf(stderr, "Unexpected ret %d (%d expected)\n", ret, expected_ret);
+		return -1;
+	}
+
+	if (err != expected_err) {
+		fprintf(stderr, "Unexpected errno %d (%d expected)\n", err, expected_err);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int no_process(void)
+{
+	FILE *f = NULL;
+	size_t len;
+	ssize_t count;
+	char *buf = NULL;
+	int pid, fd, ret;
+
+	printf("--- Try to dump unexisting process\n");
+
+	f = fopen(PID_MAX, "r");
+	if (!f) {
+		perror("Can't open " PID_MAX);
+		goto err;
+	}
+
+	count = getline(&buf, &len, f);
+	if (count == -1) {
+		perror("Can't read " PID_MAX);
+		goto err;
+	}
+	pid = atoi(buf);
+
+	if (!kill(pid, 0)) {
+		fprintf(stderr, "max pid is taken\n");
+		goto err;
+	}
+
+	get_base_req();
+	criu_set_pid(pid);
+	ret = criu_dump();
+	if (check_resp(ret, -EBADE, errno, ESRCH))
+		goto err;
+
+	printf("   `- Success\n");
+	return 0;
+err:
+	if (f)
+		fclose(f);
+	return -1;
+
+}
+
+static int process_exists(void)
+{
+	int ret;
+
+	printf("--- Try to restore process which pid is already taken by other process\n");
+
+	get_base_req();
+	criu_set_leave_running(true);
+	if (criu_dump()) {
+		fprintf(stderr, "Self-dump failed");
+		goto err;
+	}
+
+	get_base_req();
+	ret = criu_restore();
+	if (check_resp(ret, -EBADE, errno, EEXIST))
+		goto err;
+
+	printf("   `- Success\n");
+	return 0;
+err:
+	return -1;
+}
+
+static int bad_options(void)
+{
+	int ret;
+
+	printf("--- Try to send criu invalid opts\n");
+
+	get_base_req();
+	criu_set_log_file("../file.log");
+	ret = criu_dump();
+	if (check_resp(ret, -EBADE, errno, EBADRQC))
+		goto err;
+
+	printf("   `- Success\n");
+	return 0;
+err:
+	return -1;
+}
+
+int main(int argc, char *argv[])
+{
+	int ret = 1;
+
+	if (init(argv))
+		goto out;
+
+	if (no_process() || process_exists() || bad_options())
+		goto out;
+
+	ret = 0;
+out:
+	if (dir_fd)
+		close(dir_fd);
+
+	return ret;
+}
diff --git a/test/others/libcriu/test_iters.c b/test/others/libcriu/test_iters.c
new file mode 100644
index 0000000..660da92
--- /dev/null
+++ b/test/others/libcriu/test_iters.c
@@ -0,0 +1,143 @@
+#include "criu.h"
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include "lib.h"
+
+static int wdir_fd, cur_iter = 1, cur_imgdir = -1;
+
+static int stop = 0;
+static void sh(int sig)
+{
+	stop = 1;
+}
+
+static int open_imgdir(void)
+{
+	char p[10];
+
+	sprintf(p, "%d", cur_iter);
+	mkdirat(wdir_fd, p, 0700);
+	cur_imgdir = openat(wdir_fd, p, O_DIRECTORY);
+	criu_set_images_dir_fd(cur_imgdir);
+}
+
+#define MAX_ITERS	2
+
+static int next_iter(criu_predump_info pi)
+{
+	char p[10];
+
+	printf("   `- %d iter over\n", cur_iter);
+
+	close(cur_imgdir);
+	sprintf(p, "../%d", cur_iter);
+	criu_set_parent_images(p);
+
+	cur_iter++;
+	open_imgdir();
+
+	return cur_iter < MAX_ITERS;
+}
+
+#define SUCC_ECODE	42
+
+int main(int argc, char **argv)
+{
+	int pid, ret, p[2];
+
+	wdir_fd = open(argv[2], O_DIRECTORY);
+	if (wdir_fd < 0) {
+		perror("Can't open wdir");
+		return 1;
+	}
+
+	printf("--- Start loop ---\n");
+	pipe(p);
+	pid = fork();
+	if (pid < 0) {
+		perror("Can't");
+		return -1;
+	}
+
+	if (!pid) {
+		printf("   `- loop: initializing\n");
+		if (setsid() < 0)
+			exit(1);
+		if (signal(SIGUSR1, sh) == SIG_ERR)
+			exit(1);
+
+		close(0);
+		close(1);
+		close(2);
+		close(p[0]);
+
+		ret = SUCC_ECODE;
+		write(p[1], &ret, sizeof(ret));
+		close(p[1]);
+
+		while (!stop)
+			sleep(1);
+		exit(SUCC_ECODE);
+	}
+
+	close(p[1]);
+
+	/* Wait for kid to start */
+	ret = -1;
+	read(p[0], &ret, sizeof(ret));
+	if (ret != SUCC_ECODE) {
+		printf("Error starting loop\n");
+		goto err;
+	}
+
+	/* Wait for pipe to get closed, then dump */
+	read(p[0], &ret, 1);
+	close(p[0]);
+
+	printf("--- Dump loop ---\n");
+	criu_init_opts();
+	criu_set_service_binary(argv[1]);
+	criu_set_pid(pid);
+	criu_set_log_file("dump.log");
+	criu_set_log_level(4);
+
+	open_imgdir();
+	ret = criu_dump_iters(next_iter);
+	if (ret < 0) {
+		what_err_ret_mean(ret);
+		kill(pid, SIGKILL);
+		goto err;
+	}
+
+	printf("   `- Dump succeeded\n");
+	waitpid(pid, NULL, 0);
+
+	printf("--- Restore loop ---\n");
+	criu_init_opts();
+	criu_set_log_level(4);
+	criu_set_log_file("restore.log");
+	criu_set_images_dir_fd(cur_imgdir);
+
+	pid = criu_restore_child();
+	if (pid <= 0) {
+		what_err_ret_mean(pid);
+		return -1;
+	}
+
+	printf("   `- Restore returned pid %d\n", pid);
+	kill(pid, SIGUSR1);
+err:
+	if (waitpid(pid, &ret, 0) < 0) {
+		perror("   Can't wait kid");
+		return -1;
+	}
+
+	return chk_exit(ret, SUCC_ECODE);
+}
diff --git a/test/others/libcriu/test_notify.c b/test/others/libcriu/test_notify.c
new file mode 100644
index 0000000..54fb255
--- /dev/null
+++ b/test/others/libcriu/test_notify.c
@@ -0,0 +1,97 @@
+#include "criu.h"
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "lib.h"
+
+#define SUCC_ECODE	42
+
+static int actions_called = 0;
+static int notify(char *action, criu_notify_arg_t na)
+{
+	printf("ACTION: %s\n", action);
+	actions_called++;
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	int pid, ret, fd, p[2];
+
+	printf("--- Start loop ---\n");
+	pipe(p);
+	pid = fork();
+	if (pid < 0) {
+		perror("Can't");
+		return -1;
+	}
+
+	if (!pid) {
+		printf("   `- loop: initializing\n");
+		if (setsid() < 0)
+			exit(1);
+
+		close(0);
+		close(1);
+		close(2);
+		close(p[0]);
+
+		ret = SUCC_ECODE;
+		write(p[1], &ret, sizeof(ret));
+		close(p[1]);
+
+		while (1)
+			sleep(1);
+
+		exit(SUCC_ECODE);
+	}
+
+	close(p[1]);
+
+	/* Wait for kid to start */
+	ret = -1;
+	read(p[0], &ret, sizeof(ret));
+	if (ret != SUCC_ECODE) {
+		printf("Error starting loop\n");
+		goto err;
+	}
+
+	/* Wait for pipe to get closed, then dump */
+	read(p[0], &ret, 1);
+	close(p[0]);
+
+	printf("--- Dump loop ---\n");
+	criu_init_opts();
+	criu_set_service_binary(argv[1]);
+	criu_set_pid(pid);
+	criu_set_log_file("dump.log");
+	criu_set_log_level(4);
+	criu_set_notify_cb(notify);
+	fd = open(argv[2], O_DIRECTORY);
+	criu_set_images_dir_fd(fd);
+
+	ret = criu_dump();
+	if (ret < 0) {
+		what_err_ret_mean(ret);
+		kill(pid, SIGKILL);
+		goto err;
+	}
+
+	printf("   `- Dump succeeded\n");
+	ret = 0;
+err:
+	waitpid(pid, NULL, 0);
+	if (ret || !actions_called) {
+		printf("FAIL (%d/%d)\n", ret, actions_called);
+		return 1;
+	}
+
+	printf("   `- Success (%d actions)\n", actions_called);
+	return 0;
+}
diff --git a/test/others/libcriu/test_self.c b/test/others/libcriu/test_self.c
new file mode 100644
index 0000000..c9d2a2e
--- /dev/null
+++ b/test/others/libcriu/test_self.c
@@ -0,0 +1,96 @@
+#include "criu.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include "lib.h"
+
+#define SUCC_DUMP_ECODE	41
+#define SUCC_RSTR_ECODE	43
+
+int main(int argc, char *argv[])
+{
+	int ret, fd, pid;
+
+	fd = open(argv[2], O_DIRECTORY);
+	if (fd < 0) {
+		perror("Can't open images dir");
+		return 1;
+	}
+
+	criu_init_opts();
+	criu_set_service_binary(argv[1]);
+	criu_set_images_dir_fd(fd);
+	criu_set_log_level(4);
+
+	printf("--- Start child ---\n");
+	pid = fork();
+	if (pid < 0) {
+		perror("Can't");
+		return 1;
+	}
+
+	if (!pid) {
+		/*
+		 * Child process -- dump itself, then
+		 * parent would restore us.
+		 */
+
+		close(0);
+		close(1);
+		close(2);
+		if (setsid() < 0)
+			exit(1);
+
+		criu_set_log_file("dump.log");
+		criu_set_leave_running(true);
+		ret = criu_dump();
+		if (ret < 0) {
+			what_err_ret_mean(ret);
+			exit(1);
+		}
+
+		if (ret == 0)
+			ret = SUCC_DUMP_ECODE; /* dumped OK */
+		else if (ret == 1)
+			ret = SUCC_RSTR_ECODE; /* restored OK */
+		else
+			ret = 1;
+
+		exit(ret);
+	}
+
+	printf("--- Wait for self-dump ---\n");
+	if (waitpid(pid, &ret, 0) < 0) {
+		perror("Can't wait child");
+		goto errk;
+	}
+
+	if (chk_exit(ret, SUCC_DUMP_ECODE))
+		goto errk;
+
+	printf("--- Restore ---\n");
+	criu_set_log_file("restore.log");
+
+	pid = criu_restore_child();
+	if (pid <= 0) {
+		what_err_ret_mean(pid);
+		goto err;
+	}
+
+	if (waitpid(pid, &ret, 0) < 0) {
+		perror("Can't wait rchild");
+		goto errk;
+	}
+
+	return chk_exit(ret, SUCC_RSTR_ECODE);
+
+errk:
+	kill(pid, SIGKILL);
+err:
+	return 1;
+
+}
diff --git a/test/others/libcriu/test_sub.c b/test/others/libcriu/test_sub.c
new file mode 100644
index 0000000..b435f67
--- /dev/null
+++ b/test/others/libcriu/test_sub.c
@@ -0,0 +1,107 @@
+#include "criu.h"
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "lib.h"
+
+static int stop = 0;
+static void sh(int sig)
+{
+	stop = 1;
+}
+
+#define SUCC_ECODE	42
+
+int main(int argc, char **argv)
+{
+	int pid, ret, fd, p[2];
+
+	printf("--- Start loop ---\n");
+	pipe(p);
+	pid = fork();
+	if (pid < 0) {
+		perror("Can't");
+		return -1;
+	}
+
+	if (!pid) {
+		printf("   `- loop: initializing\n");
+		if (setsid() < 0)
+			exit(1);
+		if (signal(SIGUSR1, sh) == SIG_ERR)
+			exit(1);
+
+		close(0);
+		close(1);
+		close(2);
+		close(p[0]);
+
+		ret = SUCC_ECODE;
+		write(p[1], &ret, sizeof(ret));
+		close(p[1]);
+
+		while (!stop)
+			sleep(1);
+		exit(SUCC_ECODE);
+	}
+
+	close(p[1]);
+
+	/* Wait for kid to start */
+	ret = -1;
+	read(p[0], &ret, sizeof(ret));
+	if (ret != SUCC_ECODE) {
+		printf("Error starting loop\n");
+		goto err;
+	}
+
+	/* Wait for pipe to get closed, then dump */
+	read(p[0], &ret, 1);
+	close(p[0]);
+
+	printf("--- Dump loop ---\n");
+	criu_init_opts();
+	criu_set_service_binary(argv[1]);
+	criu_set_pid(pid);
+	criu_set_log_file("dump.log");
+	criu_set_log_level(4);
+	fd = open(argv[2], O_DIRECTORY);
+	criu_set_images_dir_fd(fd);
+
+	ret = criu_dump();
+	if (ret < 0) {
+		what_err_ret_mean(ret);
+		kill(pid, SIGKILL);
+		goto err;
+	}
+
+	printf("   `- Dump succeeded\n");
+	waitpid(pid, NULL, 0);
+
+	printf("--- Restore loop ---\n");
+	criu_init_opts();
+	criu_set_log_level(4);
+	criu_set_log_file("restore.log");
+	criu_set_images_dir_fd(fd);
+
+	pid = criu_restore_child();
+	if (pid <= 0) {
+		what_err_ret_mean(pid);
+		return -1;
+	}
+
+	printf("   `- Restore returned pid %d\n", pid);
+	kill(pid, SIGUSR1);
+err:
+	if (waitpid(pid, &ret, 0) < 0) {
+		perror("   Can't wait kid");
+		return -1;
+	}
+
+	return chk_exit(ret, SUCC_ECODE);
+}
diff --git a/test/others/mem-snap/Makefile b/test/others/mem-snap/Makefile
new file mode 100644
index 0000000..7779a99
--- /dev/null
+++ b/test/others/mem-snap/Makefile
@@ -0,0 +1,2 @@
+run:
+	./run.sh
diff --git a/test/others/mem-snap/run-predump-2.sh b/test/others/mem-snap/run-predump-2.sh
new file mode 100755
index 0000000..809612e
--- /dev/null
+++ b/test/others/mem-snap/run-predump-2.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+source ../../env.sh || exit 1
+
+function fail {
+	echo "$@"
+	exit 1
+}
+set -x
+
+IMGDIR="dump/"
+
+rm -rf "$IMGDIR"
+mkdir "$IMGDIR"
+
+function launch_test {
+	echo "Launching test"
+	cd ../../zdtm/live/static/
+	make cleanout
+	make maps04
+	make maps04.pid || fail "Can't start test"
+	PID=$(cat maps04.pid)
+	kill -0 $PID || fail "Test didn't start"
+	cd -
+}
+
+function stop_test {
+	wtime=1
+	cd ../../zdtm/live/static/
+	make maps04.stop
+	cat maps04.out | fgrep PASS || fail "Test failed"
+	echo "OK"
+}
+
+launch_test
+
+echo "Taking plain dump"
+
+mkdir "$IMGDIR/dump-1/"
+${CRIU} dump -D "$IMGDIR/dump-1/" -o dump.log -t ${PID} -v4 || fail "Fail to dump"
+
+sleep 1
+echo "Restore to check it works"
+${CRIU} restore -D "${IMGDIR}/dump-1/" -o restore.log -d -v4 || fail "Fail to restore server"
+
+stop_test
+
+
+launch_test
+
+echo "Taking pre and plain dumps"
+
+echo "Pre-dump"
+mkdir "$IMGDIR/dump-2/"
+mkdir "$IMGDIR/dump-2/pre/"
+${CRIU} pre-dump -D "$IMGDIR/dump-2/pre/" -o dump.log -t ${PID} -v4 || fail "Fail to pre-dump"
+
+echo "Plain dump"
+mkdir "$IMGDIR/dump-2/plain/"
+${CRIU} dump -D "$IMGDIR/dump-2/plain/" -o dump.log -t ${PID} -v4 --prev-images-dir=../pre/ --track-mem || fail "Fail to dump"
+
+sleep 1
+echo "Restore"
+${CRIU} restore -D "${IMGDIR}/dump-2/plain/" -o restore.log -d -v4 || fail "Fail to restore server"
+
+stop_test
diff --git a/test/others/mem-snap/run-predump.sh b/test/others/mem-snap/run-predump.sh
new file mode 100755
index 0000000..073784a
--- /dev/null
+++ b/test/others/mem-snap/run-predump.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+source ../../env.sh || exit 1
+
+USEPS=0
+
+if [ "$1" = "-s" ]; then
+	echo "Will test via page-server"
+	USEPS=1
+	shift
+fi
+
+NRSNAP=${1:-3}
+SPAUSE=${2:-4}
+PORT=12345
+
+function fail {
+	echo "$@"
+	exit 1
+}
+set -x
+
+IMGDIR="dump/"
+
+rm -rf "$IMGDIR"
+mkdir "$IMGDIR"
+
+echo "Launching test"
+cd ../../zdtm//live/static/
+make cleanout
+make mem-touch
+make mem-touch.pid || fail "Can't start test"
+PID=$(cat mem-touch.pid)
+kill -0 $PID || fail "Test didn't start"
+cd -
+
+echo "Making $NRSNAP pre-dumps"
+
+for SNAP in $(seq 1 $NRSNAP); do
+	sleep $SPAUSE
+	mkdir "$IMGDIR/$SNAP/"
+	if [ $SNAP -eq 1 ] ; then
+		# First pre-dump
+		cmd="pre-dump"
+		args="--track-mem -R"
+	elif [ $SNAP -eq $NRSNAP ]; then
+		# Last dump
+		cmd="dump"
+		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem"
+	else
+		# Other pre-dumps
+		cmd="pre-dump"
+		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem -R"
+	fi
+
+	if [ $USEPS -eq 1 ]; then
+		${CRIU} page-server -D "${IMGDIR}/$SNAP/" -o ps.log --port ${PORT} -v4 &
+		PS_PID=$!
+		ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
+	else
+		ps_args=""
+	fi
+
+	${CRIU} $cmd -D "${IMGDIR}/$SNAP/" -o dump.log -t ${PID} -v4 $args $ps_args || fail "Fail to dump"
+	if [ $USEPS -eq 1 ]; then
+		wait $PS_PID
+	fi
+done
+
+echo "Restoring"
+${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log -d -v4 || fail "Fail to restore server"
+
+cd ../../zdtm//live/static/
+make mem-touch.stop
+cat mem-touch.out | fgrep PASS || fail "Test failed"
+
+echo "Test PASSED"
diff --git a/test/others/mem-snap/run-snap-auto-dedup.sh b/test/others/mem-snap/run-snap-auto-dedup.sh
new file mode 100755
index 0000000..c0d8779
--- /dev/null
+++ b/test/others/mem-snap/run-snap-auto-dedup.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+
+source ../../env.sh || exit 1
+
+USEPS=0
+
+if [ "$1" = "-s" ]; then
+	echo "Will test via page-server"
+	USEPS=1
+	shift
+fi
+
+NRSNAP=${1:-3}
+SPAUSE=${2:-4}
+PORT=12345
+
+function fail {
+	echo "$@"
+	exit 1
+}
+set -x
+
+IMGDIR="dump/"
+
+rm -rf "$IMGDIR"
+mkdir "$IMGDIR"
+
+echo "Launching test"
+cd ../../zdtm//live/static/
+make cleanout
+make mem-touch
+make mem-touch.pid || fail "Can't start test"
+PID=$(cat mem-touch.pid)
+kill -0 $PID || fail "Test didn't start"
+cd -
+
+echo "Making $NRSNAP snapshots"
+
+for SNAP in $(seq 1 $NRSNAP); do
+	sleep $SPAUSE
+	mkdir "$IMGDIR/$SNAP/"
+	if [ $SNAP -eq 1 ] ; then
+		# First snapshot -- no parent, keep running
+		args="--track-mem -R"
+	elif [ $SNAP -eq $NRSNAP ]; then
+		# Last snapshot -- has parent, kill afterwards
+		size_first_2=$(du -sh -BK  dump/2/pages-*.img | grep -Eo '[0-9]+' | head -1)
+		size_first_1=$(du -sh -BK  dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
+		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem --auto-dedup"
+	else
+		# Other snapshots -- have parent, keep running
+		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem -R"
+	fi
+
+	if [ $USEPS -eq 1 ]; then
+		${CRIU} page-server -D "${IMGDIR}/$SNAP/" -o ps.log --auto-dedup --port ${PORT} -v4 &
+		PS_PID=$!
+		ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
+	else
+		ps_args=""
+	fi
+
+	${CRIU} dump -D "${IMGDIR}/$SNAP/" -o dump.log -t ${PID} -v4 $args $ps_args || fail "Fail to dump"
+	if [ $USEPS -eq 1 ]; then
+		wait $PS_PID
+	fi
+done
+
+size_last_2=$(du -sh -BK dump/2/pages-*.img | grep -Eo '[0-9]+' | head -1)
+size_last_1=$(du -sh -BK dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
+
+dedup_ok_2=1
+if [ $size_first_2 -gt $size_last_2 ]; then
+	dedup_ok_2=0
+fi
+
+dedup_ok_1=1
+if [ $size_first_1 -gt $size_last_1 ]; then
+	dedup_ok_1=0
+fi
+
+echo "Restoring"
+${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log -d -v4 || fail "Fail to restore server"
+
+cd ../../zdtm//live/static/
+make mem-touch.stop
+cat mem-touch.out | fgrep PASS || fail "Test failed"
+
+if [[ $dedup_ok_2 -ne 0 || $dedup_ok_1 -ne 0 ]]; then
+	fail "Dedup test failed"
+fi
+
+echo "Test PASSED"
diff --git a/test/others/mem-snap/run-snap-dedup-on-restore.sh b/test/others/mem-snap/run-snap-dedup-on-restore.sh
new file mode 100755
index 0000000..5821d8a
--- /dev/null
+++ b/test/others/mem-snap/run-snap-dedup-on-restore.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+source ../../env.sh || exit 1
+
+USEPS=0
+
+if [ "$1" = "-s" ]; then
+	echo "Will test via page-server"
+	USEPS=1
+	shift
+fi
+
+NRSNAP=${1:-3}
+SPAUSE=${2:-4}
+PORT=12345
+
+function fail {
+	echo "$@"
+	exit 1
+}
+set -x
+
+IMGDIR="dump/"
+
+rm -rf "$IMGDIR"
+mkdir "$IMGDIR"
+
+echo "Launching test"
+cd ../../zdtm//live/static/
+make cleanout
+make mem-touch
+make mem-touch.pid || fail "Can't start test"
+PID=$(cat mem-touch.pid)
+kill -0 $PID || fail "Test didn't start"
+cd -
+
+echo "Making $NRSNAP snapshots"
+
+for SNAP in $(seq 1 $NRSNAP); do
+	sleep $SPAUSE
+	mkdir "$IMGDIR/$SNAP/"
+	if [ $SNAP -eq 1 ] ; then
+		# First snapshot -- no parent, keep running
+		args="--track-mem -R"
+	elif [ $SNAP -eq $NRSNAP ]; then
+		# Last snapshot -- has parent, kill afterwards
+		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem --auto-dedup"
+	else
+		# Other snapshots -- have parent, keep running
+		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem -R --auto-dedup"
+	fi
+
+	if [ $USEPS -eq 1 ]; then
+		${CRIU} page-server -D "${IMGDIR}/$SNAP/" -o ps.log --auto-dedup --port ${PORT} -v4 &
+		PS_PID=$!
+		ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
+	else
+		ps_args=""
+	fi
+
+	${CRIU} dump -D "${IMGDIR}/$SNAP/" -o dump.log -t ${PID} -v4 $args $ps_args || fail "Fail to dump"
+	if [ $USEPS -eq 1 ]; then
+		wait $PS_PID
+	fi
+done
+
+echo "Restoring"
+${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log --auto-dedup -d -v4 || fail "Fail to restore server"
+
+size_last3=$(du -sh -BK dump/3/pages-*.img | grep -Eo '[0-9]+' | head -1)
+size_last2=$(du -sh -BK dump/2/pages-*.img | grep -Eo '[0-9]+' | head -1)
+size_last1=$(du -sh -BK dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
+
+restore_dedup_ok=0
+if [[ $size_last1 -ne 0 || $size_last2 -ne 0 || $size_last3 -ne 0 ]]; then
+	restore_dedup_ok=1
+fi
+
+cd ../../zdtm//live/static/
+make mem-touch.stop
+cat mem-touch.out | fgrep PASS || fail "Test failed"
+
+if [ $restore_dedup_ok -ne 0 ]; then
+	fail "Dedup test failed"
+fi
+
+echo "Test PASSED"
diff --git a/test/others/mem-snap/run-snap-dedup.sh b/test/others/mem-snap/run-snap-dedup.sh
new file mode 100755
index 0000000..f59342e
--- /dev/null
+++ b/test/others/mem-snap/run-snap-dedup.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+
+source ../../env.sh || exit 1
+
+USEPS=0
+
+if [ "$1" = "-s" ]; then
+	echo "Will test via page-server"
+	USEPS=1
+	shift
+fi
+
+NRSNAP=${1:-3}
+SPAUSE=${2:-4}
+PORT=12345
+
+function fail {
+	echo "$@"
+	exit 1
+}
+set -x
+
+IMGDIR="dump/"
+
+rm -rf "$IMGDIR"
+mkdir "$IMGDIR"
+
+echo "Launching test"
+cd ../../zdtm/live/static/
+make cleanout
+make mem-touch
+make mem-touch.pid || fail "Can't start test"
+PID=$(cat mem-touch.pid)
+kill -0 $PID || fail "Test didn't start"
+cd -
+
+echo "Making $NRSNAP snapshots"
+
+for SNAP in $(seq 1 $NRSNAP); do
+	sleep $SPAUSE
+	mkdir "$IMGDIR/$SNAP/"
+	if [ $SNAP -eq 1 ] ; then
+		# First snapshot -- no parent, keep running
+		args="--track-mem -R"
+	elif [ $SNAP -eq $NRSNAP ]; then
+		# Last snapshot -- has parent, kill afterwards
+		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem"
+	else
+		# Other snapshots -- have parent, keep running
+		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem -R"
+	fi
+
+	if [ $USEPS -eq 1 ]; then
+		${CRIU} page-server -D "${IMGDIR}/$SNAP/" -o ps.log --port ${PORT} -v4 &
+		PS_PID=$!
+		ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
+	else
+		ps_args=""
+	fi
+
+	${CRIU} dump -D "${IMGDIR}/$SNAP/" -o dump.log -t ${PID} -v4 $args $ps_args || fail "Fail to dump"
+	if [ $USEPS -eq 1 ]; then
+		wait $PS_PID
+	fi
+done
+
+echo "Dedup test"
+
+size_first_2=$(du -sh -BK  dump/2/pages-*.img | grep -Eo '[0-9]+' | head -1)
+size_first_1=$(du -sh -BK  dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
+
+${CRIU} dedup -D "${IMGDIR}/$NRSNAP/"
+
+size_last_2=$(du -sh -BK dump/2/pages-*.img | grep -Eo '[0-9]+' | head -1)
+size_last_1=$(du -sh -BK dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
+
+dedup_ok_2=1
+dedup_ok_1=1
+
+if [ $size_first_2 -gt $size_last_2 ]; then
+	dedup_ok_2=0
+fi
+
+if [ $size_first_1 -gt $size_last_1 ]; then
+	dedup_ok_1=0
+fi
+
+echo "Restoring"
+${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log -d -v4 || fail "Fail to restore server"
+
+cd ../../zdtm/live/static/
+make mem-touch.stop
+cat mem-touch.out | fgrep PASS || fail "Test failed"
+
+if [[ $dedup_ok_2 -ne 0 || $dedup_ok_1 -ne 0 ]]; then
+	fail "Dedup test failed"
+fi
+
+echo "Test PASSED"
diff --git a/test/others/mem-snap/run-snap-maps04.sh b/test/others/mem-snap/run-snap-maps04.sh
new file mode 100755
index 0000000..97c4939
--- /dev/null
+++ b/test/others/mem-snap/run-snap-maps04.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+source ../../env.sh || exit 1
+
+USEPS=0
+
+if [ "$1" = "-s" ]; then
+	echo "Will test via page-server"
+	USEPS=1
+	shift
+fi
+
+NRSNAP=1
+SPAUSE=${2:-4}
+PORT=12345
+
+function fail {
+	echo "$@"
+	exit 1
+}
+set -x
+
+IMGDIR="dump"
+CURDIR=${pwd}
+if ! mount | fgrep "$CURDIR/$IMGDIR" ; then
+	rm -rf "$IMGDIR"
+	mkdir "$IMGDIR"
+
+	mount -t tmpfs -o size=1500M,nr_inodes=10k,mode=700 tmpfs $IMGDIR
+fi
+rm -rf "$IMGDIR/*"
+
+echo "Launching test"
+make -C ../../zdtm//live/static/ cleanout
+make -C ../../zdtm//live/static/ maps04
+make -C ../../zdtm//live/static/ maps04.pid || fail "Can't start test"
+PID=$(cat ../../zdtm//live/static/maps04.pid)
+kill -0 $PID || fail "Test haven't started"
+
+mkdir "$IMGDIR/$NRSNAP/"
+
+if [ $USEPS -eq 1 ] ; then
+	${CRIU} page-server -D "${IMGDIR}/$NRSNAP/" -o ps.log --port ${PORT} -d -v4 #&
+	PS_PID=$!
+	ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
+else
+	ps_args=""
+fi
+
+${CRIU} dump -D "${IMGDIR}/$NRSNAP/" -o dump.log -t ${PID} -v4 $ps_args || fail "Fail to dump"
+if [ $USEPS -eq 1 ] ; then
+	wait $PS_PID
+fi
+
+echo "Restoring"
+${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log --auto-dedup -d -v4 || fail "Fail to restore"
+
+make -C ../../zdtm//live/static/ maps04.stop
+sleep 1
+
+cat "../zdtm/live/static/maps04.out" | fgrep PASS || fail "Test failed"
+
+size=$(du -sh -BK  dump/1/pages-*.img | grep -Eo '[0-9]+' | head -1)
+if [ $size -ne 0 ] ; then
+	fail "Size not null"
+fi
+
+echo "Test PASSED"
diff --git a/test/others/mem-snap/run-snap.sh b/test/others/mem-snap/run-snap.sh
new file mode 100755
index 0000000..6aca4d9
--- /dev/null
+++ b/test/others/mem-snap/run-snap.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+source ../../env.sh || exit 1
+
+USEPS=0
+
+if [ "$1" = "-s" ]; then
+	echo "Will test via page-server"
+	USEPS=1
+	shift
+fi
+
+NRSNAP=${1:-3}
+SPAUSE=${2:-4}
+PORT=12345
+
+function fail {
+	echo "$@"
+	exit 1
+}
+set -x
+
+IMGDIR="dump/"
+
+rm -rf "$IMGDIR"
+mkdir "$IMGDIR"
+
+echo "Launching test"
+cd ../../zdtm/live/static/
+make cleanout
+make mem-touch
+make mem-touch.pid || fail "Can't start test"
+PID=$(cat mem-touch.pid)
+kill -0 $PID || fail "Test didn't start"
+cd -
+
+echo "Making $NRSNAP snapshots"
+
+for SNAP in $(seq 1 $NRSNAP); do
+	sleep $SPAUSE
+	mkdir "$IMGDIR/$SNAP/"
+	if [ $SNAP -eq 1 ] ; then
+		# First snapshot -- no parent, keep running
+		args="--track-mem -R"
+	elif [ $SNAP -eq $NRSNAP ]; then
+		# Last snapshot -- has parent, kill afterwards
+		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem"
+	else
+		# Other snapshots -- have parent, keep running
+		args="--prev-images-dir=../$((SNAP - 1))/ --track-mem -R"
+	fi
+
+	if [ $USEPS -eq 1 ]; then
+		${CRIU} page-server -D "${IMGDIR}/$SNAP/" -o ps.log --port ${PORT} -v4 &
+		PS_PID=$!
+		ps_args="--page-server --address 127.0.0.1 --port=${PORT}"
+	else
+		ps_args=""
+	fi
+
+	${CRIU} dump -D "${IMGDIR}/$SNAP/" -o dump.log -t ${PID} -v4 $args $ps_args || fail "Fail to dump"
+	if [ $USEPS -eq 1 ]; then
+		wait $PS_PID
+	fi
+done
+
+echo "Restoring"
+${CRIU} restore -D "${IMGDIR}/$NRSNAP/" -o restore.log -d -v4 || fail "Fail to restore server"
+
+cd ../../zdtm/live/static/
+make mem-touch.stop
+cat mem-touch.out | fgrep PASS || fail "Test failed"
+
+echo "Test PASSED"
diff --git a/test/others/mem-snap/run.sh b/test/others/mem-snap/run.sh
new file mode 100755
index 0000000..b3995ec
--- /dev/null
+++ b/test/others/mem-snap/run.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# Don't execute tests, which use maps04, they are executed by zdtm
+
+set -e
+
+#./run-predump-2.sh
+./run-predump.sh
+./run-snap-auto-dedup.sh
+./run-snap-dedup-on-restore.sh
+./run-snap-dedup.sh
+#./run-snap-maps04.sh
+./run-snap.sh
diff --git a/test/others/mounts/ext/Makefile b/test/others/mounts/ext/Makefile
new file mode 100644
index 0000000..282fba0
--- /dev/null
+++ b/test/others/mounts/ext/Makefile
@@ -0,0 +1,13 @@
+all: ext-mount.so ns_init
+
+ext-mount.so: ext-mount.c
+	gcc -g -Werror -Wall -shared -nostartfiles ext-mount.c -o ext-mount.so -iquote ../../../include -fPIC
+
+ns_init: ns_init.o
+	gcc -static $< -o $@
+
+ns_init.o: ns_init.c
+	gcc -c $< -o $@
+
+run: all
+	./run.sh
diff --git a/test/others/mounts/ext/ext-mount.c b/test/others/mounts/ext/ext-mount.c
new file mode 100644
index 0000000..e5e974b
--- /dev/null
+++ b/test/others/mounts/ext/ext-mount.c
@@ -0,0 +1,101 @@
+#include <sys/mount.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "criu-plugin.h"
+#include "criu-log.h"
+
+#define IMG_NAME	"ext-mount-test-%d.img"
+
+extern cr_plugin_init_t cr_plugin_init;
+extern cr_plugin_dump_ext_mount_t cr_plugin_dump_ext_mount;
+extern cr_plugin_restore_ext_mount_t cr_plugin_restore_ext_mount;
+
+int cr_plugin_init(void)
+{
+	pr_info("Initialized ext mount c/r\n");
+	return 0;
+}
+
+int cr_plugin_dump_ext_mount(char *mountpoint, int id)
+{
+	char *aux, *dst;
+	int fd;
+	char img[64];
+
+	pr_info("Check for ext mount %s being mine\n", mountpoint);
+	aux = strrchr(mountpoint, '/');
+	if (!aux) {
+		pr_err("Bad path provided\n");
+		return -ENOTSUP;
+	}
+
+	dst = getenv("EMP_MOUNTPOINT");
+	if (!dst) {
+		pr_err("No EMP_MOUNTPOINT env\n");
+		return -1;
+	}
+
+	if (strcmp(aux + 1, dst)) {
+		pr_info("Not mine\n");
+		return -ENOTSUP;
+	}
+
+	pr_info("Dumping my mount %d\n", id);
+	sprintf(img, IMG_NAME, id);
+	fd = openat(criu_get_image_dir(), img,
+			O_RDWR | O_CREAT | O_TRUNC, 0600);
+	if (fd < 0) {
+		pr_perror("Can't open image");
+		return -1;
+	}
+
+	close(fd);
+	return 0;
+}
+
+int cr_plugin_restore_ext_mount(int id, char *mountpoint, char *old_root, int *is_file)
+{
+	int fd;
+	char img[64], src[256], *src_file;
+
+	pr_info("Restoring my mount %d?\n", id);
+	sprintf(img, IMG_NAME, id);
+	fd = openat(criu_get_image_dir(), img, O_RDONLY);
+	if (fd < 0) {
+		if (errno == ENOENT)
+			return -ENOTSUP;
+		pr_perror("Can't open my image");
+		return -1;
+	}
+	close(fd);
+
+	src_file = getenv("EMP_ROOT_P");
+	if (!src_file) {
+		pr_err("Can't get EMP_ROOT_P env\n");
+		return -1;
+	}
+
+	if (creat(mountpoint, 0600) < 0) {
+		if (errno != EEXIST) {
+			pr_perror("Can't make mountpoint");
+			return -1;
+		}
+	}
+
+	if (is_file)
+		*is_file = 1;
+
+	sprintf(src, "/%s/%s", old_root, src_file);
+	pr_info("Mount %s -> %s\n", src, mountpoint);
+	if (mount(src, mountpoint, NULL, MS_BIND, NULL) < 0) {
+		pr_perror("Can't bind mount");
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/test/others/mounts/ext/ns_init.c b/test/others/mounts/ext/ns_init.c
new file mode 100644
index 0000000..e85bf9d
--- /dev/null
+++ b/test/others/mounts/ext/ns_init.c
@@ -0,0 +1,143 @@
+#define _GNU_SOURCE
+#include <sched.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/mount.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+
+static void sigh(int sig)
+{
+}
+
+int main(int argc, char **argv)
+{
+	int start[2];
+	char res;
+	pid_t pid;
+
+	/*
+	 * Usage:
+	 * run <pidfile> <root> <log-file-name> <file-to-check> <contents-to-check>
+	 */
+
+	if (getpid() == 1) {
+		int fd;
+		struct sigaction sa = {};
+		sigset_t mask;
+
+		if (setsid() == -1) {
+			fprintf(stderr, "setsid: %m\n");
+			return 1;
+		}
+
+		sa.sa_handler = sigh;
+		sigaction(SIGTERM, &sa, NULL);
+
+		if (chdir(argv[2]))
+			return 1;
+
+		fd = open(argv[3], O_WRONLY|O_CREAT|O_TRUNC|O_APPEND, 0600);
+		if (fd < 0)
+			return 1;
+
+		dup2(fd, 1);
+		dup2(fd, 2);
+		close(fd);
+		close(0);
+
+		if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
+			fprintf(stderr, "mount(/, S_REC | MS_PRIVATE)): %m");
+			return 1;
+		}
+
+		mkdir("oldm");
+		if (pivot_root(".", "./oldm") < 0)
+			return 1;
+
+		umount2("/oldm", MNT_DETACH);
+
+		mkdir("/proc");
+		if (mount("zdtm_proc", "/proc", "proc", 0, NULL)) {
+			fprintf(stderr, "mount(/proc): %m");
+			return 1;
+		}
+
+		sigemptyset(&mask);
+		sigaddset(&mask, SIGTERM);
+		sigprocmask(SIG_BLOCK, &mask, NULL);
+
+		fd = atoi(argv[1]);
+		write(fd, "!", 1);
+		close(fd);
+
+		sigemptyset(&mask);
+		sigsuspend(&mask);
+
+		printf("Woken UP\n");
+		printf("Reading %s for [%s]\n", argv[4], argv[5]);
+		{
+			FILE *f;
+			char buf[128];
+
+			f = fopen(argv[4], "r");
+			if (!f)
+				perror("No file with message");
+			else {
+				memset(buf, 0, sizeof(buf));
+				fgets(buf, sizeof(buf), f);
+				fclose(f);
+				printf("Got [%s]\n", buf);
+
+				if (!strcmp(buf, argv[5]))
+					printf("PASS\n");
+			}
+		}
+
+		exit(0);
+	}
+
+	if (unshare(CLONE_NEWNS | CLONE_NEWPID))
+		return 1;
+
+	pipe(start);
+	pid = fork();
+	if (pid == 0) {
+		char *nargv[7], aux[10];
+
+		close(start[0]);
+		sprintf(aux, "%d", start[1]);
+		nargv[0] = argv[0];
+		nargv[1] = aux;
+		nargv[2] = argv[2];
+		nargv[3] = argv[3];
+		nargv[4] = argv[4];
+		nargv[5] = argv[5];
+		nargv[6] = NULL;
+
+		execv(argv[0], nargv);
+		exit(0);
+	}
+
+	close(start[1]);
+	res = 'F';
+	read(start[0], &res, 1);
+	if (res != '!') {
+		printf("Failed to start\n");
+		return 1;
+	}
+
+	printf("Container w/ tests started\n");
+	{
+		FILE *pidf;
+		pidf = fopen(argv[1], "w");
+		fprintf(pidf, "%d", pid);
+		fclose(pidf);
+	}
+
+	return 0;
+}
diff --git a/test/others/mounts/ext/run.sh b/test/others/mounts/ext/run.sh
new file mode 100755
index 0000000..ff2a2d8
--- /dev/null
+++ b/test/others/mounts/ext/run.sh
@@ -0,0 +1,125 @@
+#!/bin/bash
+
+set -x
+
+function fail {
+	echo $@
+	exit 1
+}
+
+make || fail "Can't compile library or ns init"
+
+criu="../../../criu/criu"
+
+# New root for namespace
+NSROOT="nsroot"
+# External file with contents (exported for plugin.restore)
+EMP_ROOT="external_file"
+export EMP_ROOT_P="$(pwd)/$EMP_ROOT"
+# Internal file as seen from namespace (exported for plugin.dump)
+export EMP_MOUNTPOINT="file"
+# Message in a file to check visibility
+FMESSAGE="tram-pam-pam"
+# Binary of namespace's init
+NS_INIT="ns_init"
+# File with namespace init pid
+PIDF="pidf"
+
+start_ns()
+{
+	#
+	# Prepare the namespace's FS layout
+	#
+	mkdir $NSROOT
+	echo -n "$FMESSAGE" > "$EMP_ROOT"
+	mount --bind "$NSROOT" "$NSROOT"
+	mount --make-private "$NSROOT"
+	touch "$NSROOT/$EMP_MOUNTPOINT"
+	mount --bind "$EMP_ROOT" "$NSROOT/$EMP_MOUNTPOINT" || fail "Can't prepare fs for ns"
+
+	#
+	# Start the namespace's init
+	#
+	cp $NS_INIT "$NSROOT/"
+	"./$NSROOT/$NS_INIT" "$PIDF" "$NSROOT" "log" "$EMP_MOUNTPOINT" "$FMESSAGE" || fail "Can't start namespace"
+	umount "$NSROOT/$EMP_MOUNTPOINT"
+
+	echo "Namespace started, pid $(cat $PIDF)"
+}
+
+stop_ns()
+{
+	#
+	# Kill the init
+	#
+
+	kill -TERM $(cat $PIDF)
+	sleep 2 # Shitty, but...
+	umount $NSROOT
+
+	if [ -z "$1" ]; then
+		rm -f "$NSROOT/log"
+	else
+		mv "$NSROOT/log" "$1"
+	fi
+
+	rm -f "$PIDF" "$EMP_ROOT" "$NSROOT/$NS_INIT" "$NSROOT/log" "$NSROOT/$EMP_MOUNTPOINT"
+	rmdir "$NSROOT/oldm"
+	rmdir "$NSROOT/proc"
+	rmdir "$NSROOT"
+}
+
+DDIR="dump"
+rm -rf $DDIR
+mkdir $DDIR
+
+chk_pass()
+{
+	tail -n1 $1 | fgrep -q "PASS"
+}
+
+#
+# Test 1: handle external mount with plugin
+#
+
+test_plugin()
+{
+	echo "=== Testing how plugin works"
+	mkdir "$DDIR/plugin/"
+	start_ns
+
+	$criu dump    -D "$DDIR/plugin/" -v4 -o "dump.log" --lib=$(pwd) \
+			-t $(cat pidf) || { stop_ns; return 1; }
+
+	$criu restore -D "$DDIR/plugin/" -v4 -o "rstr.log" --lib=$(pwd) \
+			-d --root="$(pwd)/$NSROOT" --pidfile=$PIDF || { stop_ns; return 1; }
+
+	echo "Restored, checking results"
+	mv "$DDIR/plugin/$PIDF" .
+	stop_ns "$DDIR/plugin/ns.log"
+	chk_pass "$DDIR/plugin/ns.log"
+}
+
+test_ext_mount_map()
+{
+	echo "=== Testing how --ext-mount-map works"
+	mkdir "$DDIR/ext_mount_map/"
+	start_ns
+
+	$criu dump    -D "$DDIR/ext_mount_map/" -v4 -o "dump.log" \
+			-t $(cat pidf) --ext-mount-map "/$EMP_MOUNTPOINT:TM" || { stop_ns; return 1; }
+
+	$criu restore -D "$DDIR/ext_mount_map/" -v4 -o "rstr.log" \
+			-d --root="$(pwd)/$NSROOT" --pidfile=$PIDF --ext-mount-map "TM:$EMP_ROOT_P" || { stop_ns; return 1; }
+
+	echo "Restored, checking results"
+	mv "$DDIR/ext_mount_map/$PIDF" .
+	stop_ns "$DDIR/ext_mount_map/ns.log"
+	chk_pass "$DDIR/ext_mount_map/ns.log"
+}
+
+test_plugin || exit 1
+test_ext_mount_map || exit 1
+
+echo "All tests passed"
+exit 0
diff --git a/test/others/mounts/mounts.py b/test/others/mounts/mounts.py
new file mode 100755
index 0000000..7f11d7d
--- /dev/null
+++ b/test/others/mounts/mounts.py
@@ -0,0 +1,31 @@
+import os
+import tempfile, random
+
+def mount(src, dst, shared, private, slave):
+	cmd = "mount"
+	if shared:
+		cmd += " --make-shared"
+	if private:
+		cmd += " --make-private"
+	if slave:
+		cmd += " --make-slave"
+	if src:
+		cmd += " --bind '%s' '%s'" % (src, dst)
+	else:
+		cmd += " -t tmpfs none '%s'" % (dst)
+
+	print cmd
+	ret = os.system(cmd)
+	if ret:
+		print "failed"
+
+root = tempfile.mkdtemp(prefix = "root.mount", dir = "/tmp")
+mount(None, root, 1, 0, 0)
+mounts = [root]
+
+for i in xrange(10):
+	dstdir = random.choice(mounts)
+	dst = tempfile.mkdtemp(prefix = "mount", dir = dstdir)
+	src = random.choice(mounts + [None])
+	mount(src, dst, random.randint(0,100) > 50, random.randint(0,100) > 90, random.randint(0,100) > 50)
+	mounts.append(dst)
diff --git a/test/others/mounts/mounts.sh b/test/others/mounts/mounts.sh
new file mode 100755
index 0000000..19116d0
--- /dev/null
+++ b/test/others/mounts/mounts.sh
@@ -0,0 +1,27 @@
+[ -z "$INMNTNS" ] && {
+	export INMNTNS=`pwd`
+	export INMNTNS_PID=$$
+	unshare -m -- setsid bash -x "$0" "$@" < /dev/null &> mounts.log &
+	echo $! > mounts.pid
+	while :; do
+		sleep 1
+	done
+}
+
+cd $INMNTNS
+
+mount --make-rprivate /
+
+for i in `cat /proc/self/mounts | awk '{ print $2 }'`; do
+	[ '/' = "$i" ] && continue
+	[ '/proc' = "$i" ] && continue
+	[ '/dev' = "$i" ] && continue
+	echo $i
+	umount -l $i
+done
+
+python mounts.py
+kill $INMNTNS_PID
+while :; do
+	sleep 10
+done
diff --git a/test/others/mounts/run.sh b/test/others/mounts/run.sh
new file mode 100755
index 0000000..6428239
--- /dev/null
+++ b/test/others/mounts/run.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+CRIU=../../../criu
+set -x
+
+mkdir -p dump
+
+./mounts.sh
+pid=`cat mounts.pid`
+kill -0 $pid || exit
+
+cat /proc/$pid/mountinfo | sort -k 4
+echo "Suspend server"
+${CRIU} dump -D dump -o dump.log -t $pid -v4 || {
+	cat dump/dump.log | grep Error
+	exit 1
+}
+echo "Resume server"
+${CRIU} restore -d -D dump -o restore.log -v4 || {
+	cat dump/dump.log | grep Error
+	exit 1
+}
+cat /proc/$pid/mountinfo | sort -k 4
+kill $pid
diff --git a/test/others/overlayfs/Makefile b/test/others/overlayfs/Makefile
new file mode 100644
index 0000000..78c246b
--- /dev/null
+++ b/test/others/overlayfs/Makefile
@@ -0,0 +1,6 @@
+run:
+	./run.sh
+
+clean:
+	umount -f overlay_test/z
+	rm -rf overlay_test output checkpoint
diff --git a/test/others/overlayfs/run.sh b/test/others/overlayfs/run.sh
new file mode 100755
index 0000000..26e6ec2
--- /dev/null
+++ b/test/others/overlayfs/run.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+set -eu
+
+CRIU=../../../criu/criu
+
+setup() {
+	setup_mount
+	setsid sleep 10 3>z/file < /dev/null &> output &
+	PROC_PID=$!
+	echo "PROC_PID=$PROC_PID"
+	sleep 1
+}
+
+setup_mount() {
+	mkdir -p overlay_test
+	cd overlay_test
+	mkdir -p a b c z checkpoint
+	mount -t overlay -o lowerdir=a,upperdir=b,workdir=c overlayfs z
+}
+
+check_criu() {
+	echo "Dumping $PROC_PID..."
+	if ! $CRIU dump -D checkpoint -t "${PROC_PID}"; then
+		echo "ERROR! dump failed"
+		return 1
+	fi
+
+	echo "Restoring..."
+	if ! $CRIU restore -d -D checkpoint; then
+		echo "ERROR! restore failed"
+		return 1
+	fi
+	return 0
+}
+
+cleanup() {
+	kill -INT "${PROC_PID}" > /dev/null 2>&1
+	umount z
+	cd "${ORIG_WD}"
+	rm -rf overlay_test
+}
+
+main() {
+	ORIG_WD=$(pwd)
+	setup
+
+	check_criu || {
+		cleanup
+		exit 1
+	}
+
+	cleanup
+	echo "OverlayFS C/R successful."
+	exit 0
+}
+
+main
diff --git a/test/others/pipes/Makefile b/test/others/pipes/Makefile
new file mode 100644
index 0000000..71b16be
--- /dev/null
+++ b/test/others/pipes/Makefile
@@ -0,0 +1,14 @@
+CFLAGS += -Wall
+pipe: pipe.c
+clean:
+	rm -f pipe
+run: pipe
+	./pipe - &&		\
+	./pipe -c &&		\
+	./pipe -cl &&		\
+	./pipe -d &&		\
+	./pipe -o &&		\
+	./pipe -r &&		\
+	./pipe -dc &&		\
+	./pipe -dcl &&		\
+	true
diff --git a/test/others/pipes/pipe.c b/test/others/pipes/pipe.c
new file mode 100644
index 0000000..33ec60e
--- /dev/null
+++ b/test/others/pipes/pipe.c
@@ -0,0 +1,693 @@
+/*
+ * A simple demo/test program using criu's --inherit-fd command line
+ * option to restore a process with (1) an external pipe and (2) a
+ * new log file.
+ *
+ * Note that it's possible to restore the process without --inherit-fd,
+ * but when it reads from or writes to the pipe, it will get a broken
+ * pipe signal.
+ *
+ * Also note that changing the log file during restore has nothing to do
+ * with the pipe.  It's just a nice feature for cases where it's desirable
+ * to have a restored process use a different file then the original one.
+ * 
+ * The parent process spawns a child that will write messages to its
+ * parent through a pipe.  After a couple of messages, parent invokes
+ * criu to checkpoint the child.  Since the child exits after checkpoint,
+ * its pipe will be broken.  Parent sets up a new pipe and invokes criu
+ * to restore the child using the new pipe (instead of the old one).
+ * The restored child exits after writing a couple more messages.
+ *
+ * To make sure that fd clashes are correctly handled during restore,
+ * child can optionally open a regular file and move it to a clashing fd.
+ *
+ * Make sure CRIU_BINARY defined below points to the right criu.
+ *
+ *	$ cc -Wall -o pipe pipe.c
+ *	$ sudo ./pipe -v
+ *
+ *      The following should all succeed:
+ *
+ *	$ sudo ./pipe -q && echo OK
+ *	$ sudo ./pipe -qc && echo OK
+ *	$ sudo ./pipe -qcl && echo OK
+ *	$ sudo ./pipe -qd && echo OK
+ *	$ sudo ./pipe -qdc && echo OK
+ *	$ sudo ./pipe -qdcl && echo OK
+ *
+ *      The following should all fail:
+ *
+ *	$ sudo ./pipe -qn || echo $?
+ *	$ sudo ./pipe -qo || echo $?
+ *	$ sudo ./pipe -qr || echo $?
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/prctl.h>
+
+typedef void (*sighandler_t)(int);
+typedef unsigned long ulong;
+
+/* colors */
+#define CS_PARENT 		"\033[00;32m"
+#define CS_CHILD 		"\033[00;33m"
+#define CS_DUMP 		"\033[00;34m"
+#define CS_RESTORE 		"\033[00;35m"
+#define CE			"\033[0m"
+
+#define die(fmt, ...) do { \
+	if (!qflag) \
+		fprintf(stderr, fmt ": %m\n", __VA_ARGS__); \
+	if (getpid() == parent_pid) { \
+		(void)kill(0, 9); \
+		exit(1); \
+	} \
+	_exit(1); \
+} while (0)
+
+#define READ_FD		0	/* pipe read fd */
+#define WRITE_FD	1	/* pipe write fd */
+#define CLASH_FD	3	/* force inherit fd clash */
+
+#define MAX_FORKS	3	/* child, checkpoint, restore */
+
+#define CRIU_BINARY		"../../../criu/criu"
+#define IMG_DIR			"images"
+#define DUMP_LOG_FILE		"dump.log"
+#define RESTORE_LOG_FILE	"restore.log"
+#define RESTORE_PID_FILE	"restore.pid"
+#define INHERIT_FD_OPTION	"--inherit-fd"
+#define OLD_LOG_FILE		"/tmp/oldlog"
+#define NEW_LOG_FILE		"/tmp/newlog"
+
+/*
+ * Command line options (see usage()).
+ */
+char *cli_flags = "cdhlnoqrv";
+
+int cflag;
+int dflag;
+int lflag;
+int nflag;
+int oflag;
+int qflag;
+int rflag;
+int vflag;
+
+char pid_number[8];
+char inh_pipe_opt[16];
+char inh_pipe_arg[64];
+char inh_file_opt[16];
+char inh_file_arg[64];
+
+char *dump_argv[] = {
+	"criu", "dump",
+	"-D", IMG_DIR, "-o", DUMP_LOG_FILE,
+	"-v4",
+	"-t", pid_number,
+	NULL
+};
+
+char *restore_argv[] = {
+	"criu", "restore", "-d",
+	"-D", IMG_DIR, "-o", RESTORE_LOG_FILE,
+	"--pidfile", RESTORE_PID_FILE,
+	"-v4",
+	inh_pipe_opt, inh_pipe_arg,
+	inh_file_opt, inh_file_arg,
+	NULL
+};
+
+int max_msgs;
+int max_forks;
+int parent_pid;
+int child_pid;
+int criu_dump_pid;
+int criu_restore_pid;
+
+/* prototypes */
+void chld_handler(int signum);
+int parent(int *pipefd);
+int child(int *pipefd, int dupfd, int newfd);
+void checkpoint_child(int child_pid, int *pipefd);
+void restore_child(int *new_pipefd, char *old_pipe_name);
+void write_to_fd(int fd, char *name, int i, int newline);
+void ls_proc_fd(int fd);
+char *pipe_name(int fd);
+char *who(pid_t pid);
+void pipe_safe(int pipefd[2]);
+pid_t fork_safe(void);
+void signal_safe(int signum, sighandler_t handler);
+int open_safe(char *pathname, int flags);
+void close_safe(int fd);
+void write_safe(int fd, char *buf, int count);
+int read_safe(int fd, char *buf, int count);
+int dup_safe(int oldfd);
+void move_fd(int oldfd, int newfd);
+void mkdir_safe(char *dirname, int mode);
+void unlink_safe(char *pathname);
+void execv_safe(char *path, char *argv[], int ls);
+pid_t waitpid_safe(pid_t pid, int *status, int options, int id);
+void prctl_safe(int option, ulong arg2, ulong arg3, ulong arg4, ulong arg5);
+int dup2_safe(int oldfd, int newfd);
+
+void usage(char *cmd)
+{
+	printf("Usage: %s [%s]\n", cmd, cli_flags);
+	printf("-c\tcause a clash during restore by opening %s as fd %d\n",
+		OLD_LOG_FILE, CLASH_FD);
+	printf("-d\tdup the pipe and write to it\n");
+	printf("-l\tchange log file from %s to %s during restore\n",
+		OLD_LOG_FILE, NEW_LOG_FILE);
+
+	printf("\n");
+	printf("The following flags should cause restore failure\n");
+	printf("-n\tdo not use the %s option\n", INHERIT_FD_OPTION);
+	printf("-o\topen the pipe via /proc/<pid>/fd and write to it\n");
+	printf("-r\tspecify read end of pipe during restore\n");
+
+	printf("\n");
+	printf("Miscellaneous flags\n");
+	printf("-h\tprint this help and exit\n");
+	printf("-q\tquiet mode, don't print anything\n");
+	printf("-v\tverbose mode (list contents of /proc/<pid>/fd)\n");
+
+}
+
+int main(int argc, char *argv[])
+{
+	int ret;
+        int opt;
+	int pipefd[2];
+
+	max_msgs = 4;
+	while ((opt = getopt(argc, argv, cli_flags)) != -1) {
+		switch (opt) {
+		case 'c': cflag++; break;
+		case 'd': dflag++; max_msgs += 4; break;
+		case 'h': usage(argv[0]); return 0;
+		case 'l': lflag++; break;
+		case 'n': nflag++; break;
+		case 'o': oflag++; max_msgs += 4; break;
+		case 'q': qflag++; vflag = 0;break;
+		case 'r': rflag++; break;
+		case 'v': vflag++; qflag = 0; break;
+		default: usage(argv[0]); return 1;
+		}
+	}
+
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+	mkdir_safe(IMG_DIR, 0700);
+
+	pipe_safe(pipefd);
+	child_pid = fork_safe();
+	if (child_pid > 0) {
+		parent_pid = getpid();
+
+		signal_safe(SIGCHLD, chld_handler);
+		prctl_safe(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
+
+		close_safe(pipefd[WRITE_FD]);
+
+		ret = parent(pipefd);
+	} else {
+		/* child */
+		int dupfd = -1;
+		int openfd = -1;
+		int logfd, flags;
+
+		child_pid = getpid();
+
+		close_safe(pipefd[READ_FD]);
+		setsid();
+		logfd = open_safe(OLD_LOG_FILE, O_WRONLY | O_APPEND | O_CREAT);
+		dup2_safe(logfd, 1);
+		dup2_safe(logfd, 2);
+		close(logfd);
+		close(0);
+
+		/* open a regular file and move it to CLASH_FD */
+		if (cflag)
+			move_fd(open_safe(OLD_LOG_FILE, O_WRONLY | O_APPEND | O_CREAT), CLASH_FD);
+
+		fcntl(pipefd[WRITE_FD], F_SETFL, O_NONBLOCK | O_WRONLY);
+		/* open additional descriptors on the pipe and use them all */
+		if (dflag)
+			dupfd = dup_safe(pipefd[WRITE_FD]);
+		if (oflag) {
+			char buf[128];
+			snprintf(buf, sizeof buf, "/proc/self/fd/%d", pipefd[WRITE_FD]);
+			openfd = open_safe(buf, O_WRONLY);
+		}
+
+		ret = child(pipefd, dupfd, openfd);
+
+		flags = fcntl(pipefd[WRITE_FD], F_GETFL, 0);
+		if ((flags & O_NONBLOCK) == 0) {
+			printf("Unexpected flags %x\n", flags);
+			ret = -1;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * Parent reads message from its pipe with the child.
+ * After a couple of messages, it checkpoints the child
+ * which causes the child to exit.  Parent then creates
+ * a new pipe and restores the child.
+ */
+int parent(int *pipefd)
+{
+	char buf[32];
+	char old_pipe[32];
+	int nread;
+
+	nread = 0;
+	while (max_forks <= MAX_FORKS) {
+		if (read_safe(pipefd[READ_FD], buf, sizeof buf) == 0)
+			continue;
+		nread++;
+		if (vflag && nread == 1)
+			ls_proc_fd(-1);
+
+		if (!qflag) {
+			printf("%s read %s from %s\n", who(0), buf,
+				pipe_name(pipefd[READ_FD]));
+		}
+
+		if (nread == (max_msgs / 2)) {
+			checkpoint_child(child_pid, pipefd);
+
+			if (!nflag) {
+				/* save the old pipe's name before closing it */
+				snprintf(old_pipe, sizeof old_pipe, "%s",
+					pipe_name(pipefd[READ_FD]));
+				close_safe(pipefd[READ_FD]);
+
+				/* create a new one */
+				if (!qflag)
+					printf("%s creating a new pipe\n", who(0));
+				pipe_safe(pipefd);
+			}
+			restore_child(pipefd, old_pipe);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Child sends a total of max_messages messages to its
+ * parent, half before checkpoint and half after restore.
+ */
+int child(int *pipefd, int dupfd, int openfd)
+{
+	int i;
+	int fd;
+	int num_wfds;
+	struct timespec req = { 1, 0 };
+
+	/*
+	 * Count the number of pipe descriptors we'll be
+	 * writing to.  At least 1 (for pipefd[WRITE_FD])
+	 * and at most 3.
+	 */
+	num_wfds = 1;
+	if (dupfd >= 0)
+		num_wfds++;
+	if (openfd >= 0)
+		num_wfds++;
+
+	for (i = 0; i < max_msgs; i++) {
+		/* print first time and after checkpoint */
+		if (vflag && (i == 0 || i == (max_msgs / 2)))
+			ls_proc_fd(-1);
+
+		switch (i % num_wfds) {
+		case 0: fd = pipefd[WRITE_FD]; break;
+		case 1: fd = dflag ? dupfd : openfd; break;
+		case 2: fd = openfd; break;
+		}
+
+		write_to_fd(fd, pipe_name(pipefd[WRITE_FD]), i+1, 0);
+		if (cflag)
+			write_to_fd(CLASH_FD, "log file", i+1, 1);
+
+		/*
+		 * Since sleep will be interrupted by C/R, make sure
+		 * to sleep an entire second to minimize the chance of
+		 * writing before criu restore has exited.  If criu is
+		 * still around and we write to a broken pipe, we'll be
+		 * killed but SIGCHLD will be delivered to criu instead
+		 * of parent.
+		 */
+		while (nanosleep(&req, NULL))
+			;
+		if (!qflag)
+			printf("\n");
+	}
+
+	return 0;
+}
+
+void chld_handler(int signum)
+{
+	int status;
+	pid_t pid;
+
+	pid = waitpid_safe(-1, &status, WNOHANG, 1);
+	if (WIFEXITED(status))
+		status = WEXITSTATUS(status);
+	if (pid == child_pid) {
+		if (!qflag) {
+			printf("%s %s exited with status %d\n", who(0),
+				who(pid), status); 
+		}
+		/* if child exited successfully, we're done */
+		if (status == 0)
+			exit(0);
+		/* checkpoint kills the child */
+		if (status != 9)
+			exit(status);
+	}
+}
+
+void checkpoint_child(int child_pid, int *pipefd)
+{
+	/* prepare -t <pid> */
+	snprintf(pid_number, sizeof pid_number, "%d", child_pid);
+
+	criu_dump_pid = fork_safe();
+	if (criu_dump_pid > 0) {
+		int status;
+		pid_t pid;
+
+		pid = waitpid_safe(criu_dump_pid, &status, 0, 2);
+		if (WIFEXITED(status))
+			status = WEXITSTATUS(status);
+		if (!qflag) {
+			printf("%s %s exited with status %d\n", who(0),
+				who(pid), status);
+		}
+		if (status)
+			exit(status);
+	} else {
+		close(pipefd[READ_FD]);
+		criu_dump_pid = getpid();
+		execv_safe(CRIU_BINARY, dump_argv, 0);
+	}
+}
+
+void restore_child(int *new_pipefd, char *old_pipe_name)
+{
+	char buf[64];
+
+	criu_restore_pid = fork_safe();
+	if (criu_restore_pid > 0) {
+		int status;
+		pid_t pid;
+
+		if (!nflag)
+			close_safe(new_pipefd[WRITE_FD]);
+
+		pid = waitpid_safe(criu_restore_pid, &status, 0, 3);
+		if (WIFEXITED(status))
+			status = WEXITSTATUS(status);
+		if (!qflag) {
+			printf("%s %s exited with status %d\n", who(0),
+				who(pid), status);
+		}
+		if (status)
+			exit(status);
+	} else {
+		criu_restore_pid = getpid();
+
+		if (!nflag) {
+			/*
+			 * We should close the read descriptor of the new pipe
+			 * and use its write descriptor to call criu restore.
+			 * But if rflag was set (for testing purposes), use the
+			 * read descriptor which should cause the application to
+			 * fail.
+			 *
+			 * Regardless of read or write descriptor, move it to a
+			 * clashing fd to test inherit fd clash resolve code.
+			 */
+			if (rflag)
+				move_fd(new_pipefd[READ_FD], CLASH_FD);
+			else {
+				close_safe(new_pipefd[READ_FD]);
+				move_fd(new_pipefd[WRITE_FD], CLASH_FD);
+			}
+
+			/* --inherit-fd fd[CLASH_FD]:pipe[xxxxxx] */
+			snprintf(inh_pipe_opt, sizeof inh_pipe_opt,
+				"%s", INHERIT_FD_OPTION);
+			snprintf(inh_pipe_arg, sizeof inh_pipe_arg, "fd[%d]:%s",
+				CLASH_FD, old_pipe_name);
+
+			if (lflag) {
+				/* create a new log file to replace the old one */
+				int filefd = open_safe(NEW_LOG_FILE, O_WRONLY | O_APPEND | O_CREAT);
+
+				/* --inherit-fd fd[x]:tmp/oldlog */
+				snprintf(inh_file_opt, sizeof inh_file_opt,
+					"%s", INHERIT_FD_OPTION);
+				snprintf(inh_file_arg, sizeof inh_file_arg,
+					"fd[%d]:%s", filefd, OLD_LOG_FILE + 1);
+
+				restore_argv[12] = inh_file_opt;
+			} else
+				restore_argv[12] = NULL;
+			restore_argv[10] = inh_pipe_opt;
+		} else
+			restore_argv[10] = NULL;
+
+		snprintf(buf, sizeof buf, "%s/%s", IMG_DIR, RESTORE_PID_FILE);
+		unlink_safe(buf);
+		execv_safe(CRIU_BINARY, restore_argv, 1);
+	}
+}
+
+void write_to_fd(int fd, char *name, int i, int newline)
+{
+	int n;
+	char buf[16];	/* fit "hello d\n" for small d */
+
+	n = snprintf(buf, sizeof buf, "hello %d", i);
+	if (!qflag)
+		printf("%s writing %s to %s via fd %d\n", who(0), buf, name, fd);
+
+	if (newline) {
+		buf[n++] = '\n';
+		buf[n] = '\0';
+	}
+	write_safe(fd, buf, strlen(buf));
+}
+
+void ls_proc_fd(int fd)
+{
+	char cmd[128];
+
+	if (qflag)
+		return;
+
+	if (fd == -1)
+		snprintf(cmd, sizeof cmd, "ls -l /proc/%d/fd", getpid());
+	else
+		snprintf(cmd, sizeof cmd, "ls -l /proc/%d/fd/%d", getpid(), fd);
+	printf("%s %s\n", who(0), cmd);
+	system(cmd);
+}
+
+char *pipe_name(int fd)
+{
+	static char pipe_name[64];
+	char path[64];
+
+	snprintf(path, sizeof path, "/proc/self/fd/%d", fd);
+	if (readlink(path, pipe_name, sizeof pipe_name) == -1)
+		die("readlink: path=%s", path);
+	return pipe_name;
+}
+
+/*
+ * Use two buffers to support two calls to 
+ * this function in a printf argument list.
+ */
+char *who(pid_t pid)
+{
+	static char pidstr1[64];
+	static char pidstr2[64];
+	static char *cp;
+	char *np;
+	char *ep;
+	int p;
+
+	p = pid ? pid : getpid();
+	if (p == parent_pid) {
+		np = "parent";
+		ep = CS_PARENT;
+	} else if (p == child_pid) {
+		np = "child";
+		ep = CS_CHILD;
+	} else if (p == criu_dump_pid) {
+		np = "dump";
+		ep = CS_DUMP;
+	} else if (p == criu_restore_pid) {
+		np = "restore";
+		ep = CS_RESTORE;
+	} else
+		np = "???";
+
+	cp = (cp == pidstr1) ? pidstr2 : pidstr1;
+	snprintf(cp, sizeof pidstr1, "%s[%s %d]", pid ? "" : ep, np, p);
+	return cp;
+}
+
+void pipe_safe(int pipefd[2])
+{
+	if (pipe(pipefd) == -1)
+		die("pipe: %p", pipefd);
+}
+
+pid_t fork_safe(void)
+{
+	pid_t pid;
+
+	if ((pid = fork()) == -1)
+		die("fork: pid=%d", pid);
+	max_forks++;
+	return pid;
+}
+
+void signal_safe(int signum, sighandler_t handler)
+{
+	if (signal(signum, handler) == SIG_ERR)
+		die("signal: signum=%d", signum);
+}
+
+int open_safe(char *pathname, int flags)
+{
+	int fd;
+
+	if ((fd = open(pathname, flags, 0777)) == -1)
+		die("open: pathname=%s", pathname);
+	return fd;
+}
+
+void close_safe(int fd)
+{
+	if (close(fd) == -1)
+		die("close: fd=%d", fd);
+}
+
+void write_safe(int fd, char *buf, int count)
+{
+	if (write(fd, buf, count) != count) {
+		die("write: fd=%d buf=\"%s\" count=%d errno=%d",
+			fd, buf, count, errno);
+	}
+}
+
+int read_safe(int fd, char *buf, int count)
+{
+	int n;
+
+	if ((n = read(fd, buf, count)) < 0)
+		die("read: fd=%d count=%d", fd, count);
+	buf[n] = '\0';
+	return n;
+}
+
+int dup_safe(int oldfd)
+{
+	int newfd;
+
+	if ((newfd = dup(oldfd)) == -1)
+		die("dup: oldfd=%d", oldfd);
+	return newfd;
+}
+
+int dup2_safe(int oldfd, int newfd)
+{
+	if (dup2(oldfd, newfd) != newfd)
+		die("dup2: oldfd=%d newfd=%d", oldfd, newfd);
+	return newfd;
+}
+
+void move_fd(int oldfd, int newfd)
+{
+	if (oldfd != newfd) {
+		dup2_safe(oldfd, newfd);
+		close_safe(oldfd);
+	}
+}
+
+void mkdir_safe(char *dirname, int mode)
+{
+	if (mkdir(dirname, mode) == -1 && errno != EEXIST)
+		die("mkdir dirname=%s mode=0x%x\n", dirname, mode);
+}
+
+void unlink_safe(char *pathname)
+{
+	if (unlink(pathname) == -1 && errno != ENOENT) {
+		die("unlink: pathname=%s\n", pathname);
+	}
+}
+
+void execv_safe(char *path, char *argv[], int ls)
+{
+	int i;
+	struct timespec req = { 0, 1000000 };
+
+	if (!qflag) {
+		printf("\n%s ", who(0));
+		for (i = 0; argv[i] != NULL; i++)
+			printf("%s ", argv[i]);
+		printf("\n");
+	}
+
+	/* give parent a chance to wait for us */
+	while (nanosleep(&req, NULL))
+		;
+
+	if (vflag && ls)
+		ls_proc_fd(-1);
+
+	execv(path, argv);
+	die("execv: path=%s", path);
+}
+
+pid_t waitpid_safe(pid_t pid, int *status, int options, int id)
+{
+	pid_t p;
+
+	p = waitpid(pid, status, options);
+	if (p == -1)
+		fprintf(stderr, "waitpid pid=%d id=%d %m\n", pid, id);
+	return p;
+}
+
+void prctl_safe(int option, ulong arg2, ulong arg3, ulong arg4, ulong arg5)
+{
+	if (prctl(option, arg2, arg3, arg4, arg5) == -1)
+		die("prctl: option=0x%x", option);
+}
diff --git a/test/others/rpc/.gitignore b/test/others/rpc/.gitignore
new file mode 100644
index 0000000..75fca39
--- /dev/null
+++ b/test/others/rpc/.gitignore
@@ -0,0 +1,3 @@
+rpc.pb-c.*
+*_pb2.py
+test-c
diff --git a/test/others/rpc/Makefile b/test/others/rpc/Makefile
new file mode 100644
index 0000000..8bd663e
--- /dev/null
+++ b/test/others/rpc/Makefile
@@ -0,0 +1,28 @@
+all: test-c rpc_pb2.py criu
+.PHONY: all
+
+CFLAGS += -g -Werror -Wall -I.
+LDFLAGS += -lprotobuf-c
+
+run: all
+	mkdir -p build
+	chmod a+rwx build
+	sudo -g '#1000' -u '#1000' ./run.sh
+
+criu: ../../../criu/criu
+	cp ../../../criu/criu $@
+	chmod u+s $@
+
+test-c: rpc.pb-c.o test-c.o
+
+test-c.o: test-c.c rpc.pb-c.c
+
+rpc_pb2.py: rpc.proto
+	protoc --proto_path=. --python_out=. rpc.proto
+
+rpc.pb-c.c: rpc.proto
+	protoc-c --proto_path=. --c_out=. rpc.proto
+
+clean:
+	rm -rf build rpc.pb-c.o test-c.o test-c rpc.pb-c.c rpc.pb-c.h rpc_pb2.py rpc_pb2.pyc criu
+.PHONY: clean
diff --git a/test/others/rpc/errno.py b/test/others/rpc/errno.py
new file mode 100755
index 0000000..666dfff
--- /dev/null
+++ b/test/others/rpc/errno.py
@@ -0,0 +1,135 @@
+#!/usr/bin/python
+# Test criu errno
+
+import socket, os, imp, sys, errno
+import rpc_pb2 as rpc
+import argparse
+
+parser = argparse.ArgumentParser(description="Test errno reported by CRIU RPC")
+parser.add_argument('socket', type = str, help = "CRIU service socket")
+parser.add_argument('dir', type = str, help = "Directory where CRIU images should be placed")
+
+args = vars(parser.parse_args())
+
+# Prepare dir for images
+class test:
+	def __init__(self):
+		self.imgs_fd = os.open(args['dir'], os.O_DIRECTORY)
+		self.s = -1
+		self._MAX_MSG_SIZE = 1024
+
+	def connect(self):
+		self.s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
+		self.s.connect(args['socket'])
+
+	def get_base_req(self):
+		req			= rpc.criu_req()
+		req.opts.log_level	= 4
+		req.opts.images_dir_fd	= self.imgs_fd
+		return req
+
+	def send_req(self, req):
+		self.connect()
+		self.s.send(req.SerializeToString())
+
+	def recv_resp(self):
+		resp = rpc.criu_resp()
+		resp.ParseFromString(self.s.recv(self._MAX_MSG_SIZE))
+		return resp
+
+	def check_resp(self, resp, typ, err):
+		if resp.type != typ:
+			raise Exception('Unexpected responce type ' + str(resp.type))
+
+		if resp.success:
+			raise Exception('Unexpected success = True')
+
+		if err and resp.cr_errno != err:
+			raise Exception('Unexpected cr_errno ' + str(resp.cr_errno))
+
+	def no_process(self):
+		print 'Try to dump unexisting process'
+		# Get pid of non-existing process.
+		# Suppose max_pid is not taken by any process.
+		with open("/proc/sys/kernel/pid_max", "r") as f:
+			pid = int(f.readline())
+			try:
+				os.kill(pid, 0)
+			except OSError:
+				pass
+			else:
+				raise Exception('max pid is taken')
+
+		# Ask criu to dump non-existing process.
+		req = self.get_base_req()
+		req.type = rpc.DUMP
+		req.opts.pid = pid
+
+		self.send_req(req)
+		resp = self.recv_resp()
+
+		self.check_resp(resp, rpc.DUMP, errno.ESRCH)
+
+		print 'Success'
+
+	def process_exists(self):
+		print 'Try to restore process which pid is already taken by other process'
+
+		# Perform self-dump
+		req = self.get_base_req()
+		req.type		= rpc.DUMP
+		req.opts.leave_running	= True
+
+		self.send_req(req)
+		resp = self.recv_resp()
+
+		if resp.success != True:
+			raise Exception('Self-dump failed')
+
+		# Ask to restore process from images of ourselves
+		req = self.get_base_req()
+		req.type = rpc.RESTORE
+
+		self.send_req(req)
+		resp = self.recv_resp()
+
+		self.check_resp(resp, rpc.RESTORE, errno.EEXIST)
+
+		print 'Success'
+
+	def bad_options(self):
+		print 'Try to send criu invalid opts'
+
+		# Subdirs are not allowed in log_file
+		req = self.get_base_req()
+		req.type = rpc.DUMP
+		req.opts.log_file = "../file.log"
+
+		self.send_req(req)
+		resp = self.recv_resp()
+
+		self.check_resp(resp, rpc.DUMP, errno.EBADRQC)
+
+		print 'Success'
+
+	def bad_request(self):
+		print 'Try to send criu invalid request type'
+
+		req = self.get_base_req()
+		req.type = rpc.NOTIFY
+
+		self.send_req(req)
+		resp = self.recv_resp()
+
+		self.check_resp(resp, rpc.EMPTY, None)
+
+		print 'Success'
+
+	def run(self):
+		self.no_process()
+		self.process_exists()
+		self.bad_options()
+		self.bad_request()
+
+t = test()
+t.run()
diff --git a/test/others/rpc/loop.sh b/test/others/rpc/loop.sh
new file mode 100755
index 0000000..0ab34ce
--- /dev/null
+++ b/test/others/rpc/loop.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+while :; do
+	sleep 1
+done
diff --git a/test/others/rpc/ps_test.py b/test/others/rpc/ps_test.py
new file mode 100755
index 0000000..82e5a50
--- /dev/null
+++ b/test/others/rpc/ps_test.py
@@ -0,0 +1,73 @@
+#!/usr/bin/python
+
+import socket, os, imp, sys, errno
+import rpc_pb2 as rpc
+import argparse
+
+parser = argparse.ArgumentParser(description="Test page-server using CRIU RPC")
+parser.add_argument('socket', type = str, help = "CRIU service socket")
+parser.add_argument('dir', type = str, help = "Directory where CRIU images should be placed")
+
+args = vars(parser.parse_args())
+
+# Connect to service socket
+s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
+s.connect(args['socket'])
+
+# Start page-server
+print 'Starting page-server'
+req			= rpc.criu_req()
+req.type		= rpc.PAGE_SERVER
+req.opts.log_file	= 'page-server.log'
+req.opts.log_level	= 4
+req.opts.images_dir_fd	= os.open(args['dir'], os.O_DIRECTORY)
+
+s.send(req.SerializeToString())
+
+resp	= rpc.criu_resp()
+MAX_MSG_SIZE = 1024
+resp.ParseFromString(s.recv(MAX_MSG_SIZE))
+
+if resp.type != rpc.PAGE_SERVER:
+	print 'Unexpected msg type'
+	sys.exit(1)
+else:
+	if resp.success:
+		# check if pid even exists
+		try:
+			os.kill(resp.ps.pid, 0)
+		except OSError as err:
+			if err.errno == errno.ESRCH:
+				print 'No process with page-server pid %d' %(resp.ps.pid)
+			else:
+				print 'Can\'t check that process %d exists' %(resp.ps.pid)
+				sys.exit(1)
+		print 'Success, page-server pid %d started on port %u' %(resp.ps.pid, resp.ps.port)
+	else:
+		print 'Failed to start page-server'
+		sys.exit(1)
+
+
+# Perform self-dump
+print 'Dumping myself using page-server'
+req.type		= rpc.DUMP
+req.opts.ps.port	= resp.ps.port
+req.opts.log_file	= 'dump.log'
+req.opts.leave_running	= True
+
+s.close()
+s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
+s.connect(args['socket'])
+s.send(req.SerializeToString())
+
+resp.ParseFromString(s.recv(MAX_MSG_SIZE))
+
+if resp.type != rpc.DUMP:
+	print 'Unexpected msg type'
+	sys.exit(1)
+else:
+	if resp.success:
+		print 'Success'
+	else:
+		print 'Fail'
+		sys.exit(1)
diff --git a/test/others/rpc/restore-loop.py b/test/others/rpc/restore-loop.py
new file mode 100755
index 0000000..70cb64e
--- /dev/null
+++ b/test/others/rpc/restore-loop.py
@@ -0,0 +1,40 @@
+#!/usr/bin/python
+
+import socket, os, imp, sys
+import rpc_pb2 as rpc
+import argparse
+
+parser = argparse.ArgumentParser(description="Test ability to restore a process from images using CRIU RPC")
+parser.add_argument('socket', type = str, help = "CRIU service socket")
+parser.add_argument('dir', type = str, help = "Directory where CRIU images could be found")
+
+args = vars(parser.parse_args())
+
+# Connect to service socket
+s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
+s.connect(args['socket'])
+
+# Create criu msg, set it's type to dump request
+# and set dump options. Checkout more options in protobuf/rpc.proto
+req			= rpc.criu_req()
+req.type		= rpc.RESTORE
+req.opts.images_dir_fd	= os.open(args['dir'], os.O_DIRECTORY)
+
+# Send request
+s.send(req.SerializeToString())
+
+# Recv response
+resp		= rpc.criu_resp()
+MAX_MSG_SIZE	= 1024
+resp.ParseFromString(s.recv(MAX_MSG_SIZE))
+
+if resp.type != rpc.RESTORE:
+	print 'Unexpected msg type'
+	sys.exit(-1)
+else:
+	if resp.success:
+		print 'Restore success'
+	else:
+		print 'Restore fail'
+		sys.exit(-1)
+	print "PID of the restored program is %d\n" %(resp.restore.pid)
diff --git a/test/others/rpc/rpc.proto b/test/others/rpc/rpc.proto
new file mode 120000
index 0000000..f65c529
--- /dev/null
+++ b/test/others/rpc/rpc.proto
@@ -0,0 +1 @@
+../../../images/rpc.proto
\ No newline at end of file
diff --git a/test/others/rpc/run.sh b/test/others/rpc/run.sh
new file mode 100755
index 0000000..ed99add
--- /dev/null
+++ b/test/others/rpc/run.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+
+set -e
+
+CRIU=./criu
+
+export PROTODIR=`readlink -f "${PWD}/../../protobuf"`
+
+echo $PROTODIR
+
+function title_print {
+	echo -e "\n**************************************************"
+	echo -e "\t\t"$1
+	echo -e "**************************************************\n"
+
+}
+
+function start_server {
+	title_print "Start service server"
+	${CRIU} service -v4 -W build -o service.log --address criu_service.socket -d --pidfile pidfile
+}
+
+function stop_server {
+	title_print "Shutdown service server"
+	kill -SIGTERM $(cat build/pidfile)
+	unlink build/pidfile
+}
+
+function test_c {
+	mkdir -p build/imgs_c
+
+	title_print "Run test-c"
+	setsid ./test-c build/criu_service.socket build/imgs_c < /dev/null &>> build/output_c
+
+	title_print "Restore test-c"
+	${CRIU} restore -v4 -o restore-c.log -D build/imgs_c
+}
+
+function test_py {
+	mkdir -p build/imgs_py
+
+	title_print "Run test-py"
+	setsid ./test.py build/criu_service.socket build/imgs_py < /dev/null &>> build/output_py
+
+	title_print "Restore test-py"
+	${CRIU} restore -v4 -o restore-py.log -D build/imgs_py
+}
+
+function test_restore_loop {
+	mkdir -p build/imgs_loop
+
+	title_print "Run loop.sh"
+	setsid ./loop.sh < /dev/null &> build/loop.log &
+	P=${!}
+	echo "pid ${P}"
+
+	title_print "Dump loop.sh"
+	${CRIU} dump -v4 -o dump-loop.log -D build/imgs_loop -t ${P}
+
+	title_print "Run restore-loop"
+	./restore-loop.py build/criu_service.socket build/imgs_loop
+	kill -SIGTERM ${P}
+}
+
+function test_ps {
+	mkdir -p build/imgs_ps
+
+	title_print "Run ps_test"
+	setsid ./ps_test.py build/criu_service.socket build/imgs_ps < /dev/null &>> build/output_ps
+}
+
+function test_errno {
+	mkdir -p build/imgs_errno
+
+	title_print "Run cr_errno test"
+	setsid ./errno.py build/criu_service.socket build/imgs_errno < /dev/null &>> build/output_errno
+}
+
+trap 'echo "FAIL"; stop_server' EXIT
+
+start_server
+
+test_c
+test_py
+test_restore_loop
+test_ps
+test_errno
+
+stop_server
+
+trap 'echo "Success"' EXIT
diff --git a/test/others/rpc/test-c.c b/test/others/rpc/test-c.c
new file mode 100644
index 0000000..490a07a
--- /dev/null
+++ b/test/others/rpc/test-c.c
@@ -0,0 +1,170 @@
+#include "rpc.pb-c.h"
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/fcntl.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#define MAX_MSG_SIZE 1024
+
+static CriuResp *recv_resp(int socket_fd)
+{
+	unsigned char buf[MAX_MSG_SIZE];
+	int len;
+	CriuResp *msg = 0;
+
+	len = read(socket_fd, buf, MAX_MSG_SIZE);
+	if (len == -1) {
+		perror("Can't read response");
+		return NULL;
+	}
+
+	msg = criu_resp__unpack(NULL, len, buf);
+	if (!msg) {
+		perror("Failed unpacking response");
+		return NULL;
+	}
+
+	return msg;
+}
+
+static int send_req(int socket_fd, CriuReq *req)
+{
+	unsigned char buf[MAX_MSG_SIZE];
+	int len;
+
+	len = criu_req__get_packed_size(req);
+
+	if (criu_req__pack(req, buf) != len) {
+		perror("Failed packing request");
+		return -1;
+	}
+
+	if (write(socket_fd, buf, len)  == -1) {
+		perror("Can't send request");
+		return -1;
+	}
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	CriuReq req		= CRIU_REQ__INIT;
+	CriuResp *resp		= NULL;
+	int fd, dir_fd;
+	int ret = 0;
+	struct sockaddr_un addr;
+	socklen_t addr_len;
+
+	if (argc != 3) {
+		fprintf(stderr, "Usage: test-c criu-service.socket imgs_dir");
+		return -1;
+	}
+
+	/*
+	 * Open a directory, in which criu will
+	 * put images
+	 */
+
+	puts(argv[2]);
+	dir_fd = open(argv[2], O_DIRECTORY);
+	if (dir_fd == -1) {
+		perror("Can't open imgs dir");
+		return -1;
+	}
+
+	/*
+	 * Set "DUMP" type of request.
+	 * Allocate CriuDumpReq.
+	 */
+	req.type			= CRIU_REQ_TYPE__DUMP;
+	req.opts			= malloc(sizeof(CriuOpts));
+	if (!req.opts) {
+			perror("Can't allocate memory for dump request");
+			return -1;
+	}
+
+	criu_opts__init(req.opts);
+
+	/*
+	 * Set dump options.
+	 * Checkout more in protobuf/rpc.proto.
+	 */
+	req.opts->has_leave_running	= true;
+	req.opts->leave_running		= true;
+	req.opts->images_dir_fd		= dir_fd;
+	req.opts->has_log_level		= true;
+	req.opts->log_level		= 4;
+
+	/*
+	 * Connect to service socket
+	 */
+	fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
+	if (fd == -1) {
+		perror("Can't create socket");
+		return -1;
+	}
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_LOCAL;
+
+	strcpy(addr.sun_path, argv[1]);
+
+	addr_len = strlen(addr.sun_path) + sizeof(addr.sun_family);
+
+	ret = connect(fd, (struct sockaddr *) &addr, addr_len);
+	if (ret == -1) {
+		perror("Cant connect to socket");
+		goto exit;
+	}
+
+	/*
+	 * Send request
+	 */
+	ret = send_req(fd, &req);
+	if (ret == -1) {
+		perror("Can't send request");
+		goto exit;
+	}
+
+	/*
+	 * Recv response
+	 */
+	resp = recv_resp(fd);
+	if (!resp) {
+		perror("Can't recv response");
+		ret = -1;
+		goto exit;
+	}
+
+	if (resp->type != CRIU_REQ_TYPE__DUMP) {
+		perror("Unexpected response type");
+		ret = -1;
+		goto exit;
+	}
+
+	/*
+	 * Check response.
+	 */
+	if (resp->success)
+		puts("Success");
+	else {
+		puts("Fail");
+		ret = -1;
+		goto exit;
+	}
+
+	if (resp->dump->has_restored && resp->dump->restored)
+		puts("Restored");
+
+exit:
+	close(fd);
+	close(dir_fd);
+	if (resp)
+		criu_resp__free_unpacked(resp, NULL);
+	return ret;
+}
diff --git a/test/others/rpc/test.py b/test/others/rpc/test.py
new file mode 100755
index 0000000..7154c00
--- /dev/null
+++ b/test/others/rpc/test.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+
+import socket, os, imp, sys
+import rpc_pb2 as rpc
+import argparse
+
+parser = argparse.ArgumentParser(description="Test dump/restore using CRIU RPC")
+parser.add_argument('socket', type = str, help = "CRIU service socket")
+parser.add_argument('dir', type = str, help = "Directory where CRIU images should be placed")
+
+args = vars(parser.parse_args())
+
+# Connect to service socket
+s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
+s.connect(args['socket'])
+
+# Create criu msg, set it's type to dump request
+# and set dump options. Checkout more options in protobuf/rpc.proto
+req			= rpc.criu_req()
+req.type		= rpc.DUMP
+req.opts.leave_running	= True
+req.opts.log_level	= 4
+req.opts.images_dir_fd	= os.open(args['dir'], os.O_DIRECTORY)
+
+# Send request
+s.send(req.SerializeToString())
+
+# Recv response
+resp		= rpc.criu_resp()
+MAX_MSG_SIZE	= 1024
+resp.ParseFromString(s.recv(MAX_MSG_SIZE))
+
+if resp.type != rpc.DUMP:
+	print 'Unexpected msg type'
+	sys.exit(-1)
+else:
+	if resp.success:
+		print 'Success'
+	else:
+		print 'Fail'
+		sys.exit(-1)
+
+	if resp.dump.restored:
+		print 'Restored'
diff --git a/test/others/security/Makefile b/test/others/security/Makefile
new file mode 100644
index 0000000..1b9120d
--- /dev/null
+++ b/test/others/security/Makefile
@@ -0,0 +1,34 @@
+DIR	:= $(shell pwd)/data
+LOOP	:= $(DIR)/loop.sh
+PIDFILE := $(DIR)/loop.pid
+IMGS	:= $(DIR)/imgs
+CRIU	:= $(DIR)/criu
+
+ROOT	:=root
+USR1	:=criu-test-user1
+USR2	:=criu-test-user2
+
+export DIR LOOP PIDFILE IMGS CRIU ROOT USR1 USR2
+
+run: testdir users
+	./run.sh
+
+testdir: ../../../criu/criu
+	mkdir -p $(DIR)
+	mkdir -p $(IMGS)
+	cp ../../../criu/criu $(CRIU)
+	chmod u+s $(CRIU)
+	cp loop.sh $(LOOP)
+	chmod 777 $(DIR)
+
+users:
+	-userdel -f $(USR1)
+	-userdel -f $(USR2)
+	useradd -M -U $(USR1)
+	useradd -M -U $(USR2)
+	usermod -a -G $(USR2) $(USR1)
+
+clean:
+	rm -rf $(DIR)
+	-userdel -f $(USR1)
+	-userdel -f $(USR2)
diff --git a/test/others/security/loop.sh b/test/others/security/loop.sh
new file mode 100755
index 0000000..0a01053
--- /dev/null
+++ b/test/others/security/loop.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+echo $$ > $1.int
+mv $1.int $1
+
+if [ "$2" == "--chgrp" ]; then
+	grps=( $(groups) )
+	newgrp ${grps[2]}
+fi
+
+while :; do
+	sleep 1
+done
diff --git a/test/others/security/run.sh b/test/others/security/run.sh
new file mode 100755
index 0000000..e75ab44
--- /dev/null
+++ b/test/others/security/run.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+
+set -x
+
+PID=
+
+function run_as {
+	echo "== Run ${LOOP} as $1"
+	echo ${PIDFILE}
+	rm -f ${PIDFILE}
+	su $1 -c "setsid ${LOOP} ${PIDFILE} $2 < /dev/null &> /dev/null &"
+	for i in `seq 100`; do
+		test -f ${PIDFILE} && break
+		sleep 1
+	done
+	PID=`cat ${PIDFILE}`
+	echo ${PID}
+}
+
+function dump_as {
+	test -d ${IMGS} && rm -rf ${IMGS}
+	mkdir -p ${IMGS}
+	echo "== Dump ${PID} as $@"
+	su $@ -c "${CRIU} dump --tree ${PID} --images-dir ${IMGS}"
+	return $?
+}
+
+function rstr_as {
+	echo "== Restore ${IMGS} as $@"
+	su $@ -c "${CRIU} restore --images-dir ${IMGS} --restore-detached"
+	return $?
+}
+
+function result {
+	local BGRED='\033[41m'
+	local BGGREEN='\033[42m'
+	local NORMAL=$(tput sgr0)
+
+	if [ $1 -ne 0 ]; then
+		echo -e "${BGRED}FAIL${NORMAL}"
+		exit 1
+	else
+		echo -e "${BGGREEN}PASS${NORMAL}"
+	fi
+}
+
+function test_root {
+	echo "==== Check that non-root can't dump/restore process owned by root"
+
+	run_as  ${ROOT}
+
+	dump_as ${USR1} ; result $((!$?))
+	dump_as ${ROOT} ; result $(($?))
+
+	rstr_as ${USR1} ; result $((!$?))
+	rstr_as ${ROOT} ; result $(($?))
+
+	kill -SIGKILL ${PID}
+}
+
+function test_other {
+	echo "==== Check that user2 can't dump/restore process owned by user1"
+
+	run_as  ${USR1}
+
+	dump_as ${USR2} ; result $((!$?))
+	dump_as ${USR1} ; result $(($?))
+
+	rstr_as ${USR2} ; result $((!$?))
+	rstr_as ${USR1} ; result $(($?))
+
+	kill -SIGKILL ${PID}
+}
+
+function test_own {
+	echo "==== Check that user1 can dump/restore his own process that changes it's gid to one from groups"
+
+	run_as  ${USR1} "--chgrp"
+
+	dump_as ${USR1} ; result $(($?))
+
+	rstr_as ${USR1} ; result $(($?))
+
+	kill -SIGKILL ${PID}
+}
+
+test_root
+test_other
+test_own
diff --git a/test/others/socketpairs/Makefile b/test/others/socketpairs/Makefile
new file mode 100644
index 0000000..dbb152c
--- /dev/null
+++ b/test/others/socketpairs/Makefile
@@ -0,0 +1,9 @@
+CFLAGS += -Wall
+socketpair: socketpair.c
+clean:
+	rm -f socketpair
+run: socketpair
+	./socketpair  &&		\
+	./socketpair -v &&		\
+	./socketpair -m4 &&		\
+	true
diff --git a/test/others/socketpairs/socketpair.c b/test/others/socketpairs/socketpair.c
new file mode 100644
index 0000000..900c3d6
--- /dev/null
+++ b/test/others/socketpairs/socketpair.c
@@ -0,0 +1,600 @@
+/*
+ * A simple demo/test program using criu's --inherit-fd command line
+ * option to restore a process with an external unix socket.
+ * Extending inherit's logic to unix sockets created by socketpair(..) syscall.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <time.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+
+typedef void (*sighandler_t)(int);
+typedef unsigned long ulong;
+
+/* colors */
+#define CS_PARENT 		"\033[00;32m"
+#define CS_CHILD 		"\033[00;33m"
+#define CS_DUMP 		"\033[00;34m"
+#define CS_RESTORE 		"\033[00;35m"
+#define CE			"\033[0m"
+
+#define die(fmt, ...) do { \
+	fprintf(stderr, fmt ": %m\n", __VA_ARGS__); \
+	if (getpid() == parent_pid) { \
+		(void)kill(0, 9); \
+		exit(1); \
+	} \
+	_exit(1); \
+} while (0)
+
+#define READ_FD		0	/* pipe read fd */
+#define WRITE_FD	1	/* pipe write fd */
+#define CLASH_FD	3	/* force inherit fd clash */
+
+#define MAX_FORKS	3	/* child, checkpoint, restore */
+
+#define CRIU_BINARY		"../../criu/criu"
+#define IMG_DIR			"images"
+#define DUMP_LOG_FILE		"dump.log"
+#define RESTORE_LOG_FILE	"restore.log"
+#define RESTORE_PID_FILE	"restore.pid"
+#define INHERIT_FD_OPTION	"--inherit-fd"
+#define OLD_LOG_FILE		"/tmp/oldlog"
+#define NEW_LOG_FILE		"/tmp/newlog"
+
+/*
+ * Command line options (see usage()).
+ */
+
+char *cli_flags = "hm:nv";
+int max_msgs = 10;
+int vflag;
+int nflag;
+
+char pid_number[8];
+char inh_unixsk_opt[16];
+char inh_unixsk_arg[64];
+char external_sk_ino[32];
+
+char *dump_argv[] = {
+	"criu", "dump",
+	"-D", IMG_DIR, "-o", DUMP_LOG_FILE,
+	"-v4",
+	external_sk_ino,
+	"-t", pid_number,
+	NULL
+};
+
+char *restore_argv[] = {
+	"criu", "restore", "-d",
+	"-D", IMG_DIR, "-o", RESTORE_LOG_FILE,
+	"--pidfile", RESTORE_PID_FILE,
+	"-v4", "-x",
+	inh_unixsk_opt, inh_unixsk_arg,
+	NULL
+};
+
+int max_forks;
+int parent_pid;
+int child_pid;
+int criu_dump_pid;
+int criu_restore_pid;
+
+/* prototypes */
+void chld_handler(int signum);
+int parent(int *socketfd, const char *ino_child_sk);
+int child(int *socketfd, int dupfd, int newfd);
+void checkpoint_child(int child_pid, int *old_socket_namefd);
+void restore_child(int *new_socketfd, const char *old_socket_name);
+void write_to_fd(int fd, char *name, int i, int newline);
+void ls_proc_fd(int fd);
+char *socket_name(int fd);
+ino_t socket_inode(int fd);
+char *who(pid_t pid);
+void socketpair_safe(int socketfd[2]);
+pid_t fork_safe(void);
+void signal_safe(int signum, sighandler_t handler);
+int open_safe(char *pathname, int flags);
+void close_safe(int fd);
+void write_safe(int fd, char *buf, int count);
+int read_safe(int fd, char *buf, int count);
+int dup_safe(int oldfd);
+void move_fd(int oldfd, int newfd);
+void mkdir_safe(char *dirname, int mode);
+void unlink_safe(char *pathname);
+void execv_safe(char *path, char *argv[], int ls);
+pid_t waitpid_safe(pid_t pid, int *status, int options, int id);
+void prctl_safe(int option, ulong arg2, ulong arg3, ulong arg4, ulong arg5);
+int dup2_safe(int oldfd, int newfd);
+
+void usage(char *cmd)
+{
+	printf("Usage: %s [%s]\n", cmd, cli_flags);
+	printf("-h\tprint this help and exit\n");
+	printf("-m\tcount of send messages (by default 10 will send from child) \n");
+	printf("-n\tdo not use the %s option\n", INHERIT_FD_OPTION);
+	printf("-v\tverbose mode (list contents of /proc/<pid>/fd)\n");
+}
+
+int main(int argc, char *argv[])
+{
+	int ret;
+	int opt;
+	int socketfd[2];
+
+	while ((opt = getopt(argc, argv, cli_flags)) != -1) {
+		switch (opt) {
+		case 'h':
+			usage(argv[0]);
+			return 0;
+		case 'm':
+			max_msgs = atoi(optarg);
+			break;
+		case 'n':
+			nflag++;
+			break;
+		case 'v':
+			vflag++;
+			break;
+		case '?':
+			if ('m' == optopt)
+				fprintf (stderr, "Option -%c requires an argument.\n", optopt);
+			else
+			fprintf (
+				stderr,
+				"Unknown option character `\\x%x'.\n",
+				optopt);
+			return 1;
+		default:
+			usage(argv[0]);
+			return 1;
+		}
+	}
+
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+	mkdir_safe(IMG_DIR, 0700);
+
+	socketpair_safe(socketfd);
+	child_pid = fork_safe();
+	if (child_pid > 0) {
+		parent_pid = getpid();
+
+		signal_safe(SIGCHLD, chld_handler);
+		prctl_safe(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
+
+		snprintf(external_sk_ino, sizeof(external_sk_ino), "--ext-unix-sk=%u",
+			(unsigned int)socket_inode(socketfd[WRITE_FD]));
+
+		char unix_sk_ino[32] = {0};
+		strcpy(unix_sk_ino, socket_name(socketfd[WRITE_FD]));
+		close_safe(socketfd[WRITE_FD]);
+		ret = parent(socketfd, unix_sk_ino);
+	} else {
+		/* child */
+		int dupfd = -1;
+		int openfd = -1;
+		int logfd;
+
+		child_pid = getpid();
+
+		close_safe(socketfd[READ_FD]);
+		setsid();
+		logfd = open_safe(OLD_LOG_FILE, O_WRONLY | O_APPEND | O_CREAT);
+		dup2_safe(logfd, 1);
+		dup2_safe(logfd, 2);
+		close(logfd);
+		close(0);
+
+		ret = child(socketfd, dupfd, openfd);
+	}
+
+	return ret;
+}
+
+/*
+ * Parent reads message from its pipe with the child.
+ * After a couple of messages, it checkpoints the child
+ * which causes the child to exit.  Parent then creates
+ * a new pipe and restores the child.
+ */
+int parent(int *socketfd, const char *ino_child_sk)
+{
+	char buf[32];
+	int nread;
+
+	nread = 0;
+	while (max_forks <= MAX_FORKS) {
+		if (read_safe(socketfd[READ_FD], buf, sizeof buf) == 0)
+			continue;
+		nread++;
+		if (vflag && nread == 1)
+			ls_proc_fd(-1);
+
+		printf(
+			"%s read %s from %s\n",
+			who(0), buf,
+			socket_name(socketfd[READ_FD]));
+
+
+		if (nread == (max_msgs / 2)) {
+			checkpoint_child(child_pid, socketfd);
+
+			if (!nflag) {
+				close_safe(socketfd[READ_FD]);
+
+				/* create a new one */
+				printf("%s creating a new socket\n", who(0));
+				socketpair_safe(socketfd);
+			}
+
+			restore_child(socketfd, ino_child_sk);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Child sends a total of max_messages messages to its
+ * parent, half before checkpoint and half after restore.
+ */
+int child(int *socketfd, int dupfd, int openfd)
+{
+	int i;
+	int fd;
+	int num_wfds;
+	struct timespec req = { 1, 0 };
+
+	/*
+	 * Count the number of pipe descriptors we'll be
+	 * writing to.  At least 1 (for socketfd[WRITE_FD])
+	 * and at most 3.
+	 */
+	num_wfds = 1;
+	if (dupfd >= 0)
+		num_wfds++;
+	if (openfd >= 0)
+		num_wfds++;
+
+	for (i = 0; i < max_msgs; i++) {
+		/* print first time and after checkpoint */
+		if (vflag && (i == 0 || i == (max_msgs / 2)))
+			ls_proc_fd(-1);
+
+		switch (i % num_wfds) {
+			case 0: fd = socketfd[WRITE_FD]; break;
+			case 1: fd = openfd; break;
+			case 2: fd = openfd; break;
+		}
+
+		write_to_fd(fd, socket_name(socketfd[WRITE_FD]), i+1, 0);
+		/*
+		 * Since sleep will be interrupted by C/R, make sure
+		 * to sleep an entire second to minimize the chance of
+		 * writing before criu restore has exited.  If criu is
+		 * still around and we write to a broken pipe, we'll be
+		 * killed but SIGCHLD will be delivered to criu instead
+		 * of parent.
+		 */
+		while (nanosleep(&req, NULL))
+			;
+		printf("\n");
+	}
+
+	return 0;
+}
+
+void chld_handler(int signum)
+{
+	int status;
+	pid_t pid;
+
+	pid = waitpid_safe(-1, &status, WNOHANG, 1);
+	if (WIFEXITED(status))
+		status = WEXITSTATUS(status);
+	if (pid == child_pid) {
+		printf("%s %s exited with status %d\n", who(0),
+			who(pid), status);
+		/* if child exited successfully, we're done */
+		if (status == 0)
+			exit(0);
+		/* checkpoint kills the child */
+		if (status != 9)
+			exit(status);
+	}
+}
+
+void checkpoint_child(int child_pid, int *socketfd)
+{
+	/* prepare -t <pid> */
+	snprintf(pid_number, sizeof pid_number, "%d", child_pid);
+
+	criu_dump_pid = fork_safe();
+	if (criu_dump_pid > 0) {
+		int status;
+		pid_t pid;
+
+		pid = waitpid_safe(criu_dump_pid, &status, 0, 2);
+		if (WIFEXITED(status))
+			status = WEXITSTATUS(status);
+		printf("%s %s exited with status %d\n", who(0),
+			who(pid), status);
+		if (status)
+			exit(status);
+	} else {
+		close(socketfd[READ_FD]);
+		criu_dump_pid = getpid();
+		execv_safe(CRIU_BINARY, dump_argv, 0);
+	}
+}
+
+void restore_child(int *new_socketfd, const char *old_sock_name)
+{
+	char buf[64];
+
+	criu_restore_pid = fork_safe();
+	if (criu_restore_pid > 0) {
+		int status;
+		pid_t pid;
+
+		if (!nflag)
+			close_safe(new_socketfd[WRITE_FD]);
+
+		pid = waitpid_safe(criu_restore_pid, &status, 0, 3);
+		if (WIFEXITED(status))
+			status = WEXITSTATUS(status);
+
+		printf("%s %s exited with status %d\n", who(0),
+			who(pid), status);
+
+		if (status)
+			exit(status);
+	} else {
+		criu_restore_pid = getpid();
+
+		if (!nflag) {
+			close_safe(new_socketfd[READ_FD]);
+			move_fd(new_socketfd[WRITE_FD], CLASH_FD);
+
+			/* --inherit-fd fd[CLASH_FD]:socket[xxxxxx] */
+			snprintf(inh_unixsk_opt, sizeof inh_unixsk_opt,
+				"%s", INHERIT_FD_OPTION);
+			snprintf(inh_unixsk_arg, sizeof inh_unixsk_arg, "fd[%d]:%s",
+				CLASH_FD, old_sock_name);
+
+			restore_argv[11] = inh_unixsk_opt;
+			restore_argv[13] = NULL;
+		} else
+			restore_argv[11] = NULL;
+
+		snprintf(buf, sizeof buf, "%s/%s", IMG_DIR, RESTORE_PID_FILE);
+		unlink_safe(buf);
+		execv_safe(CRIU_BINARY, restore_argv, 1);
+	}
+}
+
+void write_to_fd(int fd, char *name, int i, int newline)
+{
+	int n;
+	char buf[16];	/* fit "hello d\n" for small d */
+
+	n = snprintf(buf, sizeof buf, "hello %d", i);
+
+	printf("%s writing %s to %s via fd %d\n", who(0), buf, name, fd);
+
+	if (newline) {
+		buf[n++] = '\n';
+		buf[n] = '\0';
+	}
+	write_safe(fd, buf, strlen(buf));
+}
+
+void ls_proc_fd(int fd)
+{
+	char cmd[128];
+
+	if (fd == -1)
+		snprintf(cmd, sizeof cmd, "ls -l /proc/%d/fd", getpid());
+	else
+		snprintf(cmd, sizeof cmd, "ls -l /proc/%d/fd/%d", getpid(), fd);
+	printf("%s %s\n", who(0), cmd);
+	system(cmd);
+}
+
+char *socket_name(int fd)
+{
+	static char sock_name[64];
+	char path[64];
+
+	snprintf(path, sizeof path, "/proc/self/fd/%d", fd);
+	if (readlink(path, sock_name, sizeof sock_name) == -1)
+		die("readlink: path=%s", path);
+	return sock_name;
+}
+
+ino_t socket_inode(int fd)
+{
+         struct stat sbuf;
+
+         if (fstat(fd, &sbuf) == -1)
+                 die("fstat: fd=%i", fd);
+
+         return sbuf.st_ino;
+}
+
+/*
+ * Use two buffers to support two calls to
+ * this function in a printf argument list.
+ */
+char *who(pid_t pid)
+{
+	static char pidstr1[64];
+	static char pidstr2[64];
+	static char *cp;
+	char *np;
+	char *ep;
+	int p;
+
+	p = pid ? pid : getpid();
+	if (p == parent_pid) {
+		np = "parent";
+		ep = CS_PARENT;
+	} else if (p == child_pid) {
+		np = "child";
+		ep = CS_CHILD;
+	} else if (p == criu_dump_pid) {
+		np = "dump";
+		ep = CS_DUMP;
+	} else if (p == criu_restore_pid) {
+		np = "restore";
+		ep = CS_RESTORE;
+	} else
+		np = "???";
+
+	cp = (cp == pidstr1) ? pidstr2 : pidstr1;
+	snprintf(cp, sizeof pidstr1, "%s[%s %d]", pid ? "" : ep, np, p);
+	return cp;
+}
+
+void socketpair_safe(int socketfd[2])
+{
+	if (socketpair(AF_UNIX, SOCK_STREAM, 0, socketfd) == -1)
+		die("socketpair %p", socketfd);
+}
+
+pid_t fork_safe(void)
+{
+	pid_t pid;
+
+	if ((pid = fork()) == -1)
+		die("fork: pid=%d", pid);
+	max_forks++;
+	return pid;
+}
+
+void signal_safe(int signum, sighandler_t handler)
+{
+	if (signal(signum, handler) == SIG_ERR)
+		die("signal: signum=%d", signum);
+}
+
+int open_safe(char *pathname, int flags)
+{
+	int fd;
+
+	if ((fd = open(pathname, flags, 0777)) == -1)
+		die("open: pathname=%s", pathname);
+	return fd;
+}
+
+void close_safe(int fd)
+{
+	if (close(fd) == -1)
+		die("close: fd=%d", fd);
+}
+
+void write_safe(int fd, char *buf, int count)
+{
+	if (write(fd, buf, count) != count) {
+		die("write: fd=%d buf=\"%s\" count=%d errno=%d",
+			fd, buf, count, errno);
+	}
+}
+
+int read_safe(int fd, char *buf, int count)
+{
+	int n;
+
+	if ((n = read(fd, buf, count)) < 0)
+		die("read: fd=%d count=%d", fd, count);
+	buf[n] = '\0';
+	return n;
+}
+
+int dup_safe(int oldfd)
+{
+	int newfd;
+
+	if ((newfd = dup(oldfd)) == -1)
+		die("dup: oldfd=%d", oldfd);
+	return newfd;
+}
+
+int dup2_safe(int oldfd, int newfd)
+{
+	if (dup2(oldfd, newfd) != newfd)
+		die("dup2: oldfd=%d newfd=%d", oldfd, newfd);
+	return newfd;
+}
+
+void move_fd(int oldfd, int newfd)
+{
+	if (oldfd != newfd) {
+		dup2_safe(oldfd, newfd);
+		close_safe(oldfd);
+	}
+}
+
+void mkdir_safe(char *dirname, int mode)
+{
+	if (mkdir(dirname, mode) == -1 && errno != EEXIST)
+		die("mkdir dirname=%s mode=0x%x\n", dirname, mode);
+}
+
+void unlink_safe(char *pathname)
+{
+	if (unlink(pathname) == -1 && errno != ENOENT) {
+		die("unlink: pathname=%s\n", pathname);
+	}
+}
+
+void execv_safe(char *path, char *argv[], int ls)
+{
+	int i;
+	struct timespec req = { 0, 1000000 };
+
+	printf("\n%s ", who(0));
+	for (i = 0; argv[i] != NULL; i++)
+		printf("%s ", argv[i]);
+	printf("\n");
+
+	/* give parent a chance to wait for us */
+	while (nanosleep(&req, NULL))
+		;
+
+	if (vflag && ls)
+		ls_proc_fd(-1);
+
+	execv(path, argv);
+	die("execv: path=%s", path);
+}
+
+pid_t waitpid_safe(pid_t pid, int *status, int options, int id)
+{
+	pid_t p;
+
+	p = waitpid(pid, status, options);
+	if (p == -1)
+		fprintf(stderr, "waitpid pid=%d id=%d %m\n", pid, id);
+	return p;
+}
+
+void prctl_safe(int option, ulong arg2, ulong arg3, ulong arg4, ulong arg5)
+{
+	if (prctl(option, arg2, arg3, arg4, arg5) == -1)
+		die("prctl: option=0x%x", option);
+}
diff --git a/test/others/tcp/Makefile b/test/others/tcp/Makefile
new file mode 100644
index 0000000..311d68b
--- /dev/null
+++ b/test/others/tcp/Makefile
@@ -0,0 +1,11 @@
+OBJS=cln srv
+
+all: $(OBJS)
+.PHONY: all
+
+run: all
+	./run.sh
+
+clean:
+	rm -f $(OBJS)
+.PHONY: clean
diff --git a/test/others/tcp/cln.c b/test/others/tcp/cln.c
new file mode 100644
index 0000000..6275d37
--- /dev/null
+++ b/test/others/tcp/cln.c
@@ -0,0 +1,122 @@
+#include <sys/socket.h>
+#include <linux/types.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+
+#define BUF_SIZE	(1024)
+
+static char rbuf[BUF_SIZE];
+static char buf[BUF_SIZE];
+
+static int check_buf(int sk, char *buf, int count)
+{
+	int rd, i;
+
+	printf("Checking for %d bytes\n", count);
+
+	rd = 0;
+	while (rd < count) {
+		int r;
+
+		r = read(sk, rbuf + rd, count - rd);
+		if (r == 0) {
+			printf("Unexpected EOF\n");
+			return 1;
+		}
+
+		if (r < 0) {
+			perror("Can't read buf");
+			return 1;
+		}
+
+		rd += r;
+	}
+
+	for (i = 0; i < count; i++)
+		if (buf[i] != rbuf[i]) {
+			printf("Mismatch on %d byte %d != %d\n",
+					i, (int)buf[i], (int)rbuf[i]);
+			return 1;
+		}
+
+	return 0;
+}
+
+static int serve_new_conn(int in_fd, int sk)
+{
+	printf("New connection\n");
+
+	while (1) {
+		int rd, wr;
+
+		rd = read(in_fd, buf, sizeof(buf));
+		if (rd == 0)
+			break;
+		if (rd < 0) {
+			perror("Can't read from infd");
+			return 1;
+		}
+
+		printf("Read %d bytes, sending to sock\n", rd);
+
+		wr = 0;
+		while (wr < rd) {
+			int w;
+
+			w = write(sk, buf + wr, rd - wr);
+			if (w <= 0) {
+				perror("Can't write to socket");
+				return 1;
+			}
+
+			if (check_buf(sk, buf + wr, w))
+				return 1;
+
+			wr += w;
+		}
+	}
+
+	printf("Done\n");
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	int sk, port, ret;
+	struct sockaddr_in addr;
+
+	if (argc < 3) {
+		printf("Need addr, port and iters\n");
+		return -1;
+	}
+
+	sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (sk < 0) {
+		perror("Can't create socket");
+		return -1;
+	}
+
+	port = atoi(argv[2]);
+	printf("Connecting to %s:%d\n", argv[1], port);
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	ret = inet_aton(argv[1], &addr.sin_addr);
+	if (ret < 0) {
+		perror("Can't convert addr");
+		return -1;
+	}
+	addr.sin_port = htons(port);
+
+	ret = connect(sk, (struct sockaddr *)&addr, sizeof(addr));
+	if (ret < 0) {
+		perror("Can't connect");
+		return -1;
+	}
+
+	return serve_new_conn(0, sk);
+}
diff --git a/test/others/tcp/run.sh b/test/others/tcp/run.sh
new file mode 100755
index 0000000..c7f86a0
--- /dev/null
+++ b/test/others/tcp/run.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+source ../../env.sh || exit 1
+
+set -x
+
+PORT=12345
+CLN_PIPE="./clnt_pipe"
+SRV_LOG="./srv.log"
+CLN_LOG="./cln.log"
+DDIR="dump"
+
+TEXT=$(hexdump -C /dev/urandom | head -n 1)
+
+echo "Building services"
+
+make clean && make || { echo "Failed to build"; exit 1; }
+rm -rf ${DDIR} ${SRV_LOG} ${CLN_LOG} ${CLN_PIPE}
+mkdir ${DDIR}
+
+echo "Starting server"
+
+setsid ./srv ${PORT} > ${SRV_LOG} 2>&1 &
+SRV_PID=${!}
+
+echo "Starting pipe"
+mkfifo ${CLN_PIPE}
+
+echo "Starting client"
+./cln "127.0.0.1" ${PORT} < ${CLN_PIPE} > ${CLN_LOG} &
+CLN_PID=${!}
+
+exec 3>${CLN_PIPE}
+echo "Make it run"
+echo "${TEXT}" >&3
+
+function fail {
+	echo FAIL
+
+(	exec >&2
+
+	echo "$@"
+	kill -9 ${CLN_PID}
+	kill -9 ${SRV_PID}
+	echo ${CLN_LOG}:
+	cat ${CLN_LOG}
+)
+	exit 1
+}
+
+kill -s 0 ${CLN_PID} || fail "Client is dead"
+
+echo "Suspend server"
+${CRIU} dump -D ${DDIR} -o dump.log -t ${SRV_PID} --tcp-established -vvvv || fail "Fail to dump server"
+sleep 1
+echo "Resume server"
+${CRIU} restore -D ${DDIR} -o restore.log -d --tcp-established -vvvv --close 3 || fail "Fail to restore server"
+
+echo "Make client run again"
+echo "${TEXT}" >&3
+
+echo "Collect results"
+exec 3>&-
+wait ${CLN_PID} || fail "Client exits abruptly"
+kill -9 ${SRV_PID}
+
+echo PASS
diff --git a/test/others/tcp/srv.c b/test/others/tcp/srv.c
new file mode 100644
index 0000000..656cc01
--- /dev/null
+++ b/test/others/tcp/srv.c
@@ -0,0 +1,112 @@
+#include <sys/socket.h>
+#include <linux/types.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+
+static int serve_new_conn(int sk)
+{
+	int rd, wr;
+	char buf[1024];
+
+	printf("New connection\n");
+
+	while (1) {
+		rd = read(sk, buf, sizeof(buf));
+		if (!rd)
+			break;
+
+		if (rd < 0) {
+			perror("Can't read socket");
+			return 1;
+		}
+
+		wr = 0;
+		while (wr < rd) {
+			int w;
+
+			w = write(sk, buf + wr, rd - wr);
+			if (w <= 0) {
+				perror("Can't write socket");
+				return 1;
+			}
+
+			wr += w;
+		}
+	}
+
+	printf("Done\n");
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	int sk, port, ret;
+	struct sockaddr_in addr;
+
+	if (argc < 2) {
+		printf("Need port\n");
+		return -1;
+	}
+
+	/*
+	 * Let kids die themselves
+	 */
+
+	signal(SIGCHLD, SIG_IGN);
+
+	sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (sk < 0) {
+		perror("Can't create socket");
+		return -1;
+	}
+
+	port = atoi(argv[1]);
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = htonl(INADDR_ANY);
+	addr.sin_port = htons(port);
+
+	printf("Binding to port %d\n", port);
+
+	ret = bind(sk, (struct sockaddr *)&addr, sizeof(addr));
+	if (ret < 0) {
+		perror("Can't bind socket");
+		return -1;
+	}
+
+	ret = listen(sk, 16);
+	if (ret < 0) {
+		perror("Can't put sock to listen");
+		return -1;
+	}
+
+	printf("Waiting for connections\n");
+	while (1) {
+		int ask, pid;
+
+		ask = accept(sk, NULL, NULL);
+		if (ask < 0) {
+			perror("Can't accept new conn");
+			return -1;
+		}
+
+		pid = fork();
+		if (pid < 0) {
+			perror("Can't fork");
+			return -1;
+		}
+
+		if (pid > 0)
+			close(ask);
+		else {
+			close(sk);
+			ret = serve_new_conn(ask);
+			exit(ret);
+		}
+	}
+}
diff --git a/test/others/unix-callback/Makefile b/test/others/unix-callback/Makefile
new file mode 100644
index 0000000..f2993c5
--- /dev/null
+++ b/test/others/unix-callback/Makefile
@@ -0,0 +1,22 @@
+all: unix-lib.so unix-server unix-client syslog-lib.so
+
+run: all
+	./run.sh
+
+unix.pb-c.c: unix.proto
+	protoc-c --proto_path=. --c_out=. unix.proto
+
+unix-lib.so: unix-lib.c unix.pb-c.c
+	gcc -g -Werror -Wall -shared -nostartfiles unix-lib.c unix.pb-c.c -o unix-lib.so -iquote ../../include -fPIC
+
+syslog-lib.so: syslog-lib.c
+	gcc -g -Werror -Wall -shared -nostartfiles syslog-lib.c -o syslog-lib.so -iquote ../../include -fPIC
+
+unix-server: unix-server.c
+	gcc -Werror -Wall -o unix-server unix-server.c
+
+unix-client: unix-client.c
+	gcc -Werror -Wall -o unix-client unix-client.c
+
+clean:
+	rm -rf data unix-lib.so unix-server unix-client syslog-lib.so output pid unix.pb-c.*
diff --git a/test/others/unix-callback/lib/syslog-lib.so b/test/others/unix-callback/lib/syslog-lib.so
new file mode 120000
index 0000000..6a2d849
--- /dev/null
+++ b/test/others/unix-callback/lib/syslog-lib.so
@@ -0,0 +1 @@
+../syslog-lib.so
\ No newline at end of file
diff --git a/test/others/unix-callback/lib/unix-lib.so b/test/others/unix-callback/lib/unix-lib.so
new file mode 120000
index 0000000..19c491e
--- /dev/null
+++ b/test/others/unix-callback/lib/unix-lib.so
@@ -0,0 +1 @@
+../unix-lib.so
\ No newline at end of file
diff --git a/test/others/unix-callback/run.sh b/test/others/unix-callback/run.sh
new file mode 100755
index 0000000..ec5b7f5
--- /dev/null
+++ b/test/others/unix-callback/run.sh
@@ -0,0 +1,48 @@
+#!/bin/bash -x
+
+cd `dirname $0`
+
+source ../env.sh || exit 1
+
+rm -rf /tmp/criu.unix.callback.test*
+test -f pid && unlink pid
+test -f output && unlink output
+rm -rf data
+mkdir -p data
+
+./unix-server &
+srv_pid=$!
+
+for i in `seq 20`; do
+	test -f /tmp/criu.unix.callback.test && break
+	sleep 0.1
+done
+
+( setsid ./unix-client < /dev/null &> output ) &
+
+while :; do
+	test -f pid && break
+	sleep 1
+done
+
+pid=`cat pid`
+
+${CRIU} dump -D data -o dump.log -v4 --lib `pwd`/lib -t $pid || exit 1
+kill $srv_pid
+wait $srv_pid
+unlink /tmp/criu.unix.callback.test
+./unix-server &
+srv_pid=$!
+for i in `seq 20`; do
+	test -f /tmp/criu.unix.callback.test && break
+	sleep 0.1
+done
+${CRIU} restore -D data -o restore.log -v4 --lib `pwd`/lib -d || exit 1
+kill $pid
+while :; do
+	cat output | grep PASS && break
+	sleep 1
+done
+
+cat output
+kill $srv_pid
diff --git a/test/others/unix-callback/syslog-lib.c b/test/others/unix-callback/syslog-lib.c
new file mode 100644
index 0000000..c7950ca
--- /dev/null
+++ b/test/others/unix-callback/syslog-lib.c
@@ -0,0 +1,66 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "criu-plugin.h"
+#include "criu-log.h"
+
+extern cr_plugin_dump_unix_sk_t cr_plugin_dump_unix_sk;
+extern cr_plugin_restore_unix_sk_t cr_plugin_restore_unix_sk;
+
+int cr_plugin_dump_unix_sk(int sk, int id)
+{
+	struct sockaddr_un addr;
+	socklen_t addr_len = sizeof(addr);
+	char buf[4096];
+	int fd;
+
+	if (getsockname(sk, (struct sockaddr *) &addr, &addr_len) < 0)
+		return -1;
+
+	if (strncmp(addr.sun_path, "/dev/log", addr_len - sizeof(addr.sun_family)))
+		return -ENOTSUP;
+
+	snprintf(buf, sizeof(buf), "syslog-%x.img", id);
+	fd = open(buf, O_WRONLY | O_CREAT);
+	if (fd < 0)
+		return -1;
+	close(fd);
+
+	return 0;
+}
+
+int cr_plugin_restore_unix_sk(int id)
+{
+	struct sockaddr_un addr;
+	socklen_t addr_len;
+	char buf[4096];
+	int sk, fd;
+
+	snprintf(buf, sizeof(buf), "syslog-%x.img", id);
+	fd = open(buf, O_RDONLY);
+	if (fd < 0)
+		return -ENOTSUP;
+	close(fd);
+
+	sk = socket(AF_FILE, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+	if (sk == -1)
+		return sk;
+
+	addr.sun_family = AF_FILE;
+	addr_len = strlen("/dev/log");
+	strncpy(addr.sun_path, "/dev/log", addr_len);
+	addr_len += sizeof(addr.sun_family);
+	if (connect(sk, (struct sockaddr *) &addr, addr_len) == -1) {
+		close(sk);
+		return -1;
+	}
+
+	return sk;
+}
diff --git a/test/others/unix-callback/unix-client.c b/test/others/unix-callback/unix-client.c
new file mode 100644
index 0000000..69808b5
--- /dev/null
+++ b/test/others/unix-callback/unix-client.c
@@ -0,0 +1,121 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/un.h>
+#include <fcntl.h>
+
+#include <syslog.h>
+
+#define SK_NAME "/tmp/criu.unix.callback.test"
+
+#define SK_NR 2
+struct {
+	int id;
+	int sk;
+	int val;
+} sks[SK_NR];
+
+static int create_sock(int i)
+{
+	int ret, id, sk, val = time(NULL) + i * 314;
+	char buf[4096];
+	struct sockaddr_un addr;
+	socklen_t addr_len;
+
+	id = getpid() * 10 + i;
+	sk = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (sk < 0)
+		return -1;
+
+	addr.sun_family = AF_UNIX;
+	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s%d", SK_NAME, id);
+	addr_len += sizeof(addr.sun_family);
+
+	if (bind(sk, (struct sockaddr *) &addr, addr_len) < 0) {
+		perror("bind");
+		return 1;
+	}
+
+	addr.sun_family = AF_UNIX;
+	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, SK_NAME);
+	addr_len += sizeof(addr.sun_family);
+
+	if (connect(sk, (struct sockaddr *) &addr, addr_len) < 0) {
+		perror("connect");
+		return 1;
+	}
+
+	printf("init %d\n", val);
+	ret = sprintf(buf, "t%d", val);
+	if (send(sk, buf, ret, 0) < 0) {
+		perror("send");
+		return -1;
+	}
+
+	sks[i].sk = sk;
+	sks[i].val = val;
+
+	return 0;
+}
+
+static int check_sock(int i)
+{
+	int sk = sks[i].sk, val = sks[i].val;
+	char buf[4096];
+
+	if (send(sk, "r", 1, 0) < 0) {
+		perror("send(\"r\")");
+		return -1;
+	}
+
+	if (recv(sk, buf, sizeof(buf), 0) <= 0) {
+		perror("recv");
+		return -1;
+	}
+
+	printf("%s - %d\n", buf, val);
+	if (atoi(buf) != val)
+		return -1;
+
+	return 0;
+}
+
+int main()
+{
+	int i, fd;
+	sigset_t set;
+	int sig;
+
+	for (i = 0; i < SK_NR; i++)
+		if (create_sock(i))
+			return -1;
+
+	fd = open("pid", O_WRONLY | O_CREAT, 0666);
+	if (fd < 0)
+		return 1;
+	dprintf(fd, "%d\n", getpid());
+	close(fd);
+
+	openlog("test", LOG_NDELAY, LOG_USER );
+
+	sigemptyset(&set);
+	sigaddset(&set, SIGTERM);
+	sigprocmask(SIG_BLOCK, &set, NULL);
+	sigwait(&set, &sig);
+
+	syslog(LOG_CRIT, "test message");
+
+	for (i = 0; i < SK_NR; i++)
+		if (check_sock(i))
+			return -1;
+
+	printf("PASS\n");
+	return 0;
+}
+
diff --git a/test/others/unix-callback/unix-lib.c b/test/others/unix-callback/unix-lib.c
new file mode 100644
index 0000000..44b1498
--- /dev/null
+++ b/test/others/unix-callback/unix-lib.c
@@ -0,0 +1,187 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <errno.h>
+
+#include <sys/socket.h>
+#include <linux/un.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "criu-plugin.h"
+#include "criu-log.h"
+
+#include "unix.pb-c.h"
+
+extern cr_plugin_init_t cr_plugin_init;
+extern cr_plugin_dump_unix_sk_t cr_plugin_dump_unix_sk;
+extern cr_plugin_restore_unix_sk_t cr_plugin_restore_unix_sk;
+
+#define SK_NAME "/tmp/criu.unix.callback.test"
+static int get_srv_socket(void)
+{
+	struct sockaddr_un addr;
+	socklen_t addr_len;
+	int skd;
+
+	skd = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (skd < 0) {
+		pr_perror("socket");
+		return -1;
+	}
+
+	addr.sun_family = AF_UNIX;
+	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s.dump.%d", SK_NAME, getpid());
+	addr_len += sizeof(addr.sun_family);
+
+	unlink(addr.sun_path);
+	if (bind(skd, (struct sockaddr *) &addr, addr_len) < 0) {
+		pr_perror("bind");
+		return 1;
+	}
+
+	addr.sun_family = AF_UNIX;
+	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, SK_NAME);
+	addr_len += sizeof(addr.sun_family);
+
+	if (connect(skd, (struct sockaddr *) &addr, addr_len) < 0) {
+		pr_perror("connect");
+		return -1;
+	}
+
+	return skd;
+}
+
+int cr_plugin_init(void)
+{
+	return 0;
+}
+
+int cr_plugin_dump_unix_sk(int sk, int sk_id)
+{
+	struct sockaddr_un addr;
+	socklen_t addr_len = sizeof(addr);
+	char buf[4096];
+	int skd, id, ret, fd, len;
+	UnixTest e = UNIX_TEST__INIT;
+
+	if (getpeername(sk, (struct sockaddr *) &addr, &addr_len)) {
+		pr_perror("getpeername");
+		return -1;
+	}
+
+	len = addr_len - sizeof(addr.sun_family);
+	if (addr.sun_path[len - 1] == 0)
+		len--;
+
+	if (len != strlen(SK_NAME) ||
+	    strncmp(addr.sun_path, SK_NAME, strlen(SK_NAME)))
+		return -ENOTSUP;
+
+	pr_info("Dump the socket %x\n", sk_id);
+	skd = get_srv_socket();
+	if (skd < 0)
+		return -1;
+
+	addr_len = sizeof(struct sockaddr_un);
+
+	if (getsockname(sk, (struct sockaddr *) &addr, &addr_len) < 0)
+		return -1;
+
+	id = atoi(addr.sun_path + strlen(SK_NAME));
+
+	ret = sprintf(buf, "d%d", id) + 1;
+	if (send(skd, buf, ret, 0) < 0) {
+		pr_perror("send");
+		return -1;
+	}
+
+	if (recv(skd, buf, sizeof(buf), 0) <= 0)
+		return -1;
+
+	close(skd);
+
+	e.val = atoi(buf);
+	pr_err("%x: val %d\n", sk_id, e.val);
+	e.name.data = (void *)addr.sun_path;
+	e.name.len = addr_len - sizeof(addr.sun_family);
+
+	snprintf(buf, sizeof(buf), "unix-test-%x.img", sk_id);
+	fd = openat(criu_get_image_dir(), buf, O_WRONLY | O_CREAT, 0600);
+	if (fd < 0)
+		return -1;
+
+	if (unix_test__get_packed_size(&e) > sizeof(buf)) {
+		pr_err("%ld\n", unix_test__get_packed_size(&e));
+		return -1;
+	}
+
+	ret = unix_test__pack(&e, (uint8_t *) buf);
+	if (write(fd, buf, ret) != ret)
+		return -1;
+	close(fd);
+
+	return 0;
+}
+
+int cr_plugin_restore_unix_sk(int sk_id)
+{
+	struct sockaddr_un addr;
+	socklen_t addr_len;
+	int fd, sk, ret;
+	char buf[4096];
+	UnixTest *e;
+
+	snprintf(buf, sizeof(buf), "unix-test-%x.img", sk_id);
+	fd = openat(criu_get_image_dir(), buf, O_RDONLY, 0600);
+	if (fd < 0)
+		return -ENOTSUP;
+
+	ret = read(fd, buf, sizeof(buf));
+	if (ret < 0) {
+		pr_perror("read");
+		return -1;
+	}
+	close(fd);
+
+	e = unix_test__unpack(NULL, ret, (uint8_t *) buf);
+	if (e == NULL)
+		return -1;
+
+	sk = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (sk < 0) {
+		pr_perror("socket");
+		return -1;
+	}
+
+	addr.sun_family = AF_UNIX;
+	memcpy(addr.sun_path, e->name.data, e->name.len);
+	addr_len = sizeof(addr.sun_family) + e->name.len;
+
+	if (bind(sk, (struct sockaddr *) &addr, addr_len) < 0) {
+		pr_perror("bind");
+		return -1;
+	}
+
+	addr.sun_family = AF_UNIX;
+	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, SK_NAME);
+	addr_len += sizeof(addr.sun_family);
+
+	if (connect(sk, (struct sockaddr *) &addr, addr_len) < 0) {
+		pr_perror("connect");
+		return -1;
+	}
+
+	pr_err("id %d val %d\n", sk_id, e->val);
+	ret = sprintf(buf, "t%d", e->val);
+	if (send(sk, buf, ret, 0) < 0) {
+		pr_perror("send");
+		return -1;
+	}
+
+	return sk;
+}
diff --git a/test/others/unix-callback/unix-server.c b/test/others/unix-callback/unix-server.c
new file mode 100644
index 0000000..8f32f53
--- /dev/null
+++ b/test/others/unix-callback/unix-server.c
@@ -0,0 +1,104 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <linux/un.h>
+
+struct ticket
+{
+	struct ticket *next;
+	int val;
+	int id;
+};
+
+struct ticket *tickets;
+
+#define SK_NAME "/tmp/criu.unix.callback.test"
+
+int main()
+{
+	int sk, ret, id;
+	char buf[4096];
+	struct ticket *t;
+	struct sockaddr_un addr;
+	socklen_t addr_len;
+	struct stat st;
+
+	unlink(SK_NAME);
+
+	sk = socket(AF_UNIX, SOCK_DGRAM, 0);
+	if (sk < 0) {
+		perror("socket");
+		return -1;
+	}
+
+	addr.sun_family = AF_UNIX;
+	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, SK_NAME);
+	addr_len += sizeof(addr.sun_family);
+
+	if (bind(sk, (struct sockaddr *) &addr, addr_len) < 0) {
+		perror("bind");
+		return 1;
+	}
+
+	fstat(sk, &st);
+
+	while (1) {
+		addr_len = sizeof(struct sockaddr_un);
+		ret = recvfrom(sk, buf, sizeof(buf), 0, (struct sockaddr *) &addr, &addr_len);
+		if (ret == 0)
+			return 0;
+		if (ret < 0) {
+			perror("recvfrom");
+			return 1;
+		}
+		id = 0;
+		switch (buf[0]) {
+		case 'l':
+			ret = sprintf(buf, "%ld", st.st_ino);
+			if (sendto(sk, buf, ret + 1, 0, (struct sockaddr *) &addr, addr_len) < 0) {
+				perror("sendto");
+				return -1;
+			}
+			break;
+		case 't': /* ticket */
+			t = malloc(sizeof(struct ticket));
+			if (t == 0) {
+				perror("Can't allocate memory");
+				return 1;
+			}
+
+			t->val = atoi(buf + 1);
+			t->next = tickets;
+			t->id = atoi(addr.sun_path +strlen(SK_NAME));
+			printf("t: id %d val %d\n", t->id, t->val);
+			tickets = t;
+			break;
+		case 'd': /* dump */
+			id = atoi(buf + 1);
+		case 'r': /* request */
+			if (!id)
+				id = atoi(addr.sun_path + strlen(SK_NAME));
+			for (t = tickets; t; t = t->next)
+				if (t->id == id)
+					break;
+			if (t == NULL)
+				return 1;
+			printf("r: id %d val %d\n", id, t->val);
+			ret = sprintf(buf, "%d", t->val);
+			if (sendto(sk, buf, ret + 1, 0, (struct sockaddr *) &addr, addr_len) < 0) {
+				perror("sendto");
+				return 1;
+			}
+			break;
+		default:
+			return -1;
+		}
+	}
+
+	return 0;
+}
diff --git a/test/others/unix-callback/unix.proto b/test/others/unix-callback/unix.proto
new file mode 100644
index 0000000..fb06fc8
--- /dev/null
+++ b/test/others/unix-callback/unix.proto
@@ -0,0 +1,4 @@
+message unix_test {
+	required uint32 val = 1;
+	required bytes name = 2;
+}
diff --git a/test/overlayfs/Makefile b/test/overlayfs/Makefile
deleted file mode 100644
index 78c246b..0000000
--- a/test/overlayfs/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-run:
-	./run.sh
-
-clean:
-	umount -f overlay_test/z
-	rm -rf overlay_test output checkpoint
diff --git a/test/overlayfs/run.sh b/test/overlayfs/run.sh
deleted file mode 100755
index 26e6ec2..0000000
--- a/test/overlayfs/run.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/bash
-
-set -eu
-
-CRIU=../../../criu/criu
-
-setup() {
-	setup_mount
-	setsid sleep 10 3>z/file < /dev/null &> output &
-	PROC_PID=$!
-	echo "PROC_PID=$PROC_PID"
-	sleep 1
-}
-
-setup_mount() {
-	mkdir -p overlay_test
-	cd overlay_test
-	mkdir -p a b c z checkpoint
-	mount -t overlay -o lowerdir=a,upperdir=b,workdir=c overlayfs z
-}
-
-check_criu() {
-	echo "Dumping $PROC_PID..."
-	if ! $CRIU dump -D checkpoint -t "${PROC_PID}"; then
-		echo "ERROR! dump failed"
-		return 1
-	fi
-
-	echo "Restoring..."
-	if ! $CRIU restore -d -D checkpoint; then
-		echo "ERROR! restore failed"
-		return 1
-	fi
-	return 0
-}
-
-cleanup() {
-	kill -INT "${PROC_PID}" > /dev/null 2>&1
-	umount z
-	cd "${ORIG_WD}"
-	rm -rf overlay_test
-}
-
-main() {
-	ORIG_WD=$(pwd)
-	setup
-
-	check_criu || {
-		cleanup
-		exit 1
-	}
-
-	cleanup
-	echo "OverlayFS C/R successful."
-	exit 0
-}
-
-main
diff --git a/test/pipes/Makefile b/test/pipes/Makefile
deleted file mode 100644
index 71b16be..0000000
--- a/test/pipes/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-CFLAGS += -Wall
-pipe: pipe.c
-clean:
-	rm -f pipe
-run: pipe
-	./pipe - &&		\
-	./pipe -c &&		\
-	./pipe -cl &&		\
-	./pipe -d &&		\
-	./pipe -o &&		\
-	./pipe -r &&		\
-	./pipe -dc &&		\
-	./pipe -dcl &&		\
-	true
diff --git a/test/pipes/pipe.c b/test/pipes/pipe.c
deleted file mode 100644
index 28b6c99..0000000
--- a/test/pipes/pipe.c
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
- * A simple demo/test program using criu's --inherit-fd command line
- * option to restore a process with (1) an external pipe and (2) a
- * new log file.
- *
- * Note that it's possible to restore the process without --inherit-fd,
- * but when it reads from or writes to the pipe, it will get a broken
- * pipe signal.
- *
- * Also note that changing the log file during restore has nothing to do
- * with the pipe.  It's just a nice feature for cases where it's desirable
- * to have a restored process use a different file then the original one.
- * 
- * The parent process spawns a child that will write messages to its
- * parent through a pipe.  After a couple of messages, parent invokes
- * criu to checkpoint the child.  Since the child exits after checkpoint,
- * its pipe will be broken.  Parent sets up a new pipe and invokes criu
- * to restore the child using the new pipe (instead of the old one).
- * The restored child exits after writing a couple more messages.
- *
- * To make sure that fd clashes are correctly handled during restore,
- * child can optionally open a regular file and move it to a clashing fd.
- *
- * Make sure CRIU_BINARY defined below points to the right criu.
- *
- *	$ cc -Wall -o pipe pipe.c
- *	$ sudo ./pipe -v
- *
- *      The following should all succeed:
- *
- *	$ sudo ./pipe -q && echo OK
- *	$ sudo ./pipe -qc && echo OK
- *	$ sudo ./pipe -qcl && echo OK
- *	$ sudo ./pipe -qd && echo OK
- *	$ sudo ./pipe -qdc && echo OK
- *	$ sudo ./pipe -qdcl && echo OK
- *
- *      The following should all fail:
- *
- *	$ sudo ./pipe -qn || echo $?
- *	$ sudo ./pipe -qo || echo $?
- *	$ sudo ./pipe -qr || echo $?
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <time.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/wait.h>
-#include <sys/prctl.h>
-
-typedef void (*sighandler_t)(int);
-typedef unsigned long ulong;
-
-/* colors */
-#define CS_PARENT 		"\033[00;32m"
-#define CS_CHILD 		"\033[00;33m"
-#define CS_DUMP 		"\033[00;34m"
-#define CS_RESTORE 		"\033[00;35m"
-#define CE			"\033[0m"
-
-#define die(fmt, ...) do { \
-	if (!qflag) \
-		fprintf(stderr, fmt ": %m\n", __VA_ARGS__); \
-	if (getpid() == parent_pid) { \
-		(void)kill(0, 9); \
-		exit(1); \
-	} \
-	_exit(1); \
-} while (0)
-
-#define READ_FD		0	/* pipe read fd */
-#define WRITE_FD	1	/* pipe write fd */
-#define CLASH_FD	3	/* force inherit fd clash */
-
-#define MAX_FORKS	3	/* child, checkpoint, restore */
-
-#define CRIU_BINARY		"../../criu"
-#define IMG_DIR			"images"
-#define DUMP_LOG_FILE		"dump.log"
-#define RESTORE_LOG_FILE	"restore.log"
-#define RESTORE_PID_FILE	"restore.pid"
-#define INHERIT_FD_OPTION	"--inherit-fd"
-#define OLD_LOG_FILE		"/tmp/oldlog"
-#define NEW_LOG_FILE		"/tmp/newlog"
-
-/*
- * Command line options (see usage()).
- */
-char *cli_flags = "cdhlnoqrv";
-
-int cflag;
-int dflag;
-int lflag;
-int nflag;
-int oflag;
-int qflag;
-int rflag;
-int vflag;
-
-char pid_number[8];
-char inh_pipe_opt[16];
-char inh_pipe_arg[64];
-char inh_file_opt[16];
-char inh_file_arg[64];
-
-char *dump_argv[] = {
-	"criu", "dump",
-	"-D", IMG_DIR, "-o", DUMP_LOG_FILE,
-	"-v4",
-	"-t", pid_number,
-	NULL
-};
-
-char *restore_argv[] = {
-	"criu", "restore", "-d",
-	"-D", IMG_DIR, "-o", RESTORE_LOG_FILE,
-	"--pidfile", RESTORE_PID_FILE,
-	"-v4",
-	inh_pipe_opt, inh_pipe_arg,
-	inh_file_opt, inh_file_arg,
-	NULL
-};
-
-int max_msgs;
-int max_forks;
-int parent_pid;
-int child_pid;
-int criu_dump_pid;
-int criu_restore_pid;
-
-/* prototypes */
-void chld_handler(int signum);
-int parent(int *pipefd);
-int child(int *pipefd, int dupfd, int newfd);
-void checkpoint_child(int child_pid, int *pipefd);
-void restore_child(int *new_pipefd, char *old_pipe_name);
-void write_to_fd(int fd, char *name, int i, int newline);
-void ls_proc_fd(int fd);
-char *pipe_name(int fd);
-char *who(pid_t pid);
-void pipe_safe(int pipefd[2]);
-pid_t fork_safe(void);
-void signal_safe(int signum, sighandler_t handler);
-int open_safe(char *pathname, int flags);
-void close_safe(int fd);
-void write_safe(int fd, char *buf, int count);
-int read_safe(int fd, char *buf, int count);
-int dup_safe(int oldfd);
-void move_fd(int oldfd, int newfd);
-void mkdir_safe(char *dirname, int mode);
-void unlink_safe(char *pathname);
-void execv_safe(char *path, char *argv[], int ls);
-pid_t waitpid_safe(pid_t pid, int *status, int options, int id);
-void prctl_safe(int option, ulong arg2, ulong arg3, ulong arg4, ulong arg5);
-int dup2_safe(int oldfd, int newfd);
-
-void usage(char *cmd)
-{
-	printf("Usage: %s [%s]\n", cmd, cli_flags);
-	printf("-c\tcause a clash during restore by opening %s as fd %d\n",
-		OLD_LOG_FILE, CLASH_FD);
-	printf("-d\tdup the pipe and write to it\n");
-	printf("-l\tchange log file from %s to %s during restore\n",
-		OLD_LOG_FILE, NEW_LOG_FILE);
-
-	printf("\n");
-	printf("The following flags should cause restore failure\n");
-	printf("-n\tdo not use the %s option\n", INHERIT_FD_OPTION);
-	printf("-o\topen the pipe via /proc/<pid>/fd and write to it\n");
-	printf("-r\tspecify read end of pipe during restore\n");
-
-	printf("\n");
-	printf("Miscellaneous flags\n");
-	printf("-h\tprint this help and exit\n");
-	printf("-q\tquiet mode, don't print anything\n");
-	printf("-v\tverbose mode (list contents of /proc/<pid>/fd)\n");
-
-}
-
-int main(int argc, char *argv[])
-{
-	int ret;
-        int opt;
-	int pipefd[2];
-
-	max_msgs = 4;
-	while ((opt = getopt(argc, argv, cli_flags)) != -1) {
-		switch (opt) {
-		case 'c': cflag++; break;
-		case 'd': dflag++; max_msgs += 4; break;
-		case 'h': usage(argv[0]); return 0;
-		case 'l': lflag++; break;
-		case 'n': nflag++; break;
-		case 'o': oflag++; max_msgs += 4; break;
-		case 'q': qflag++; vflag = 0;break;
-		case 'r': rflag++; break;
-		case 'v': vflag++; qflag = 0; break;
-		default: usage(argv[0]); return 1;
-		}
-	}
-
-	setbuf(stdout, NULL);
-	setbuf(stderr, NULL);
-	mkdir_safe(IMG_DIR, 0700);
-
-	pipe_safe(pipefd);
-	child_pid = fork_safe();
-	if (child_pid > 0) {
-		parent_pid = getpid();
-
-		signal_safe(SIGCHLD, chld_handler);
-		prctl_safe(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
-
-		close_safe(pipefd[WRITE_FD]);
-
-		ret = parent(pipefd);
-	} else {
-		/* child */
-		int dupfd = -1;
-		int openfd = -1;
-		int logfd, flags;
-
-		child_pid = getpid();
-
-		close_safe(pipefd[READ_FD]);
-		setsid();
-		logfd = open_safe(OLD_LOG_FILE, O_WRONLY | O_APPEND | O_CREAT);
-		dup2_safe(logfd, 1);
-		dup2_safe(logfd, 2);
-		close(logfd);
-		close(0);
-
-		/* open a regular file and move it to CLASH_FD */
-		if (cflag)
-			move_fd(open_safe(OLD_LOG_FILE, O_WRONLY | O_APPEND | O_CREAT), CLASH_FD);
-
-		fcntl(pipefd[WRITE_FD], F_SETFL, O_NONBLOCK | O_WRONLY);
-		/* open additional descriptors on the pipe and use them all */
-		if (dflag)
-			dupfd = dup_safe(pipefd[WRITE_FD]);
-		if (oflag) {
-			char buf[128];
-			snprintf(buf, sizeof buf, "/proc/self/fd/%d", pipefd[WRITE_FD]);
-			openfd = open_safe(buf, O_WRONLY);
-		}
-
-		ret = child(pipefd, dupfd, openfd);
-
-		flags = fcntl(pipefd[WRITE_FD], F_GETFL, 0);
-		if ((flags & O_NONBLOCK) == 0) {
-			printf("Unexpected flags %x\n", flags);
-			ret = -1;
-		}
-	}
-
-	return ret;
-}
-
-/*
- * Parent reads message from its pipe with the child.
- * After a couple of messages, it checkpoints the child
- * which causes the child to exit.  Parent then creates
- * a new pipe and restores the child.
- */
-int parent(int *pipefd)
-{
-	char buf[32];
-	char old_pipe[32];
-	int nread;
-
-	nread = 0;
-	while (max_forks <= MAX_FORKS) {
-		if (read_safe(pipefd[READ_FD], buf, sizeof buf) == 0)
-			continue;
-		nread++;
-		if (vflag && nread == 1)
-			ls_proc_fd(-1);
-
-		if (!qflag) {
-			printf("%s read %s from %s\n", who(0), buf,
-				pipe_name(pipefd[READ_FD]));
-		}
-
-		if (nread == (max_msgs / 2)) {
-			checkpoint_child(child_pid, pipefd);
-
-			if (!nflag) {
-				/* save the old pipe's name before closing it */
-				snprintf(old_pipe, sizeof old_pipe, "%s",
-					pipe_name(pipefd[READ_FD]));
-				close_safe(pipefd[READ_FD]);
-
-				/* create a new one */
-				if (!qflag)
-					printf("%s creating a new pipe\n", who(0));
-				pipe_safe(pipefd);
-			}
-			restore_child(pipefd, old_pipe);
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Child sends a total of max_messages messages to its
- * parent, half before checkpoint and half after restore.
- */
-int child(int *pipefd, int dupfd, int openfd)
-{
-	int i;
-	int fd;
-	int num_wfds;
-	struct timespec req = { 1, 0 };
-
-	/*
-	 * Count the number of pipe descriptors we'll be
-	 * writing to.  At least 1 (for pipefd[WRITE_FD])
-	 * and at most 3.
-	 */
-	num_wfds = 1;
-	if (dupfd >= 0)
-		num_wfds++;
-	if (openfd >= 0)
-		num_wfds++;
-
-	for (i = 0; i < max_msgs; i++) {
-		/* print first time and after checkpoint */
-		if (vflag && (i == 0 || i == (max_msgs / 2)))
-			ls_proc_fd(-1);
-
-		switch (i % num_wfds) {
-		case 0: fd = pipefd[WRITE_FD]; break;
-		case 1: fd = dflag ? dupfd : openfd; break;
-		case 2: fd = openfd; break;
-		}
-
-		write_to_fd(fd, pipe_name(pipefd[WRITE_FD]), i+1, 0);
-		if (cflag)
-			write_to_fd(CLASH_FD, "log file", i+1, 1);
-
-		/*
-		 * Since sleep will be interrupted by C/R, make sure
-		 * to sleep an entire second to minimize the chance of
-		 * writing before criu restore has exited.  If criu is
-		 * still around and we write to a broken pipe, we'll be
-		 * killed but SIGCHLD will be delivered to criu instead
-		 * of parent.
-		 */
-		while (nanosleep(&req, NULL))
-			;
-		if (!qflag)
-			printf("\n");
-	}
-
-	return 0;
-}
-
-void chld_handler(int signum)
-{
-	int status;
-	pid_t pid;
-
-	pid = waitpid_safe(-1, &status, WNOHANG, 1);
-	if (WIFEXITED(status))
-		status = WEXITSTATUS(status);
-	if (pid == child_pid) {
-		if (!qflag) {
-			printf("%s %s exited with status %d\n", who(0),
-				who(pid), status); 
-		}
-		/* if child exited successfully, we're done */
-		if (status == 0)
-			exit(0);
-		/* checkpoint kills the child */
-		if (status != 9)
-			exit(status);
-	}
-}
-
-void checkpoint_child(int child_pid, int *pipefd)
-{
-	/* prepare -t <pid> */
-	snprintf(pid_number, sizeof pid_number, "%d", child_pid);
-
-	criu_dump_pid = fork_safe();
-	if (criu_dump_pid > 0) {
-		int status;
-		pid_t pid;
-
-		pid = waitpid_safe(criu_dump_pid, &status, 0, 2);
-		if (WIFEXITED(status))
-			status = WEXITSTATUS(status);
-		if (!qflag) {
-			printf("%s %s exited with status %d\n", who(0),
-				who(pid), status);
-		}
-		if (status)
-			exit(status);
-	} else {
-		close(pipefd[READ_FD]);
-		criu_dump_pid = getpid();
-		execv_safe(CRIU_BINARY, dump_argv, 0);
-	}
-}
-
-void restore_child(int *new_pipefd, char *old_pipe_name)
-{
-	char buf[64];
-
-	criu_restore_pid = fork_safe();
-	if (criu_restore_pid > 0) {
-		int status;
-		pid_t pid;
-
-		if (!nflag)
-			close_safe(new_pipefd[WRITE_FD]);
-
-		pid = waitpid_safe(criu_restore_pid, &status, 0, 3);
-		if (WIFEXITED(status))
-			status = WEXITSTATUS(status);
-		if (!qflag) {
-			printf("%s %s exited with status %d\n", who(0),
-				who(pid), status);
-		}
-		if (status)
-			exit(status);
-	} else {
-		criu_restore_pid = getpid();
-
-		if (!nflag) {
-			/*
-			 * We should close the read descriptor of the new pipe
-			 * and use its write descriptor to call criu restore.
-			 * But if rflag was set (for testing purposes), use the
-			 * read descriptor which should cause the application to
-			 * fail.
-			 *
-			 * Regardless of read or write descriptor, move it to a
-			 * clashing fd to test inherit fd clash resolve code.
-			 */
-			if (rflag)
-				move_fd(new_pipefd[READ_FD], CLASH_FD);
-			else {
-				close_safe(new_pipefd[READ_FD]);
-				move_fd(new_pipefd[WRITE_FD], CLASH_FD);
-			}
-
-			/* --inherit-fd fd[CLASH_FD]:pipe[xxxxxx] */
-			snprintf(inh_pipe_opt, sizeof inh_pipe_opt,
-				"%s", INHERIT_FD_OPTION);
-			snprintf(inh_pipe_arg, sizeof inh_pipe_arg, "fd[%d]:%s",
-				CLASH_FD, old_pipe_name);
-
-			if (lflag) {
-				/* create a new log file to replace the old one */
-				int filefd = open_safe(NEW_LOG_FILE, O_WRONLY | O_APPEND | O_CREAT);
-
-				/* --inherit-fd fd[x]:tmp/oldlog */
-				snprintf(inh_file_opt, sizeof inh_file_opt,
-					"%s", INHERIT_FD_OPTION);
-				snprintf(inh_file_arg, sizeof inh_file_arg,
-					"fd[%d]:%s", filefd, OLD_LOG_FILE + 1);
-
-				restore_argv[12] = inh_file_opt;
-			} else
-				restore_argv[12] = NULL;
-			restore_argv[10] = inh_pipe_opt;
-		} else
-			restore_argv[10] = NULL;
-
-		snprintf(buf, sizeof buf, "%s/%s", IMG_DIR, RESTORE_PID_FILE);
-		unlink_safe(buf);
-		execv_safe(CRIU_BINARY, restore_argv, 1);
-	}
-}
-
-void write_to_fd(int fd, char *name, int i, int newline)
-{
-	int n;
-	char buf[16];	/* fit "hello d\n" for small d */
-
-	n = snprintf(buf, sizeof buf, "hello %d", i);
-	if (!qflag)
-		printf("%s writing %s to %s via fd %d\n", who(0), buf, name, fd);
-
-	if (newline) {
-		buf[n++] = '\n';
-		buf[n] = '\0';
-	}
-	write_safe(fd, buf, strlen(buf));
-}
-
-void ls_proc_fd(int fd)
-{
-	char cmd[128];
-
-	if (qflag)
-		return;
-
-	if (fd == -1)
-		snprintf(cmd, sizeof cmd, "ls -l /proc/%d/fd", getpid());
-	else
-		snprintf(cmd, sizeof cmd, "ls -l /proc/%d/fd/%d", getpid(), fd);
-	printf("%s %s\n", who(0), cmd);
-	system(cmd);
-}
-
-char *pipe_name(int fd)
-{
-	static char pipe_name[64];
-	char path[64];
-
-	snprintf(path, sizeof path, "/proc/self/fd/%d", fd);
-	if (readlink(path, pipe_name, sizeof pipe_name) == -1)
-		die("readlink: path=%s", path);
-	return pipe_name;
-}
-
-/*
- * Use two buffers to support two calls to 
- * this function in a printf argument list.
- */
-char *who(pid_t pid)
-{
-	static char pidstr1[64];
-	static char pidstr2[64];
-	static char *cp;
-	char *np;
-	char *ep;
-	int p;
-
-	p = pid ? pid : getpid();
-	if (p == parent_pid) {
-		np = "parent";
-		ep = CS_PARENT;
-	} else if (p == child_pid) {
-		np = "child";
-		ep = CS_CHILD;
-	} else if (p == criu_dump_pid) {
-		np = "dump";
-		ep = CS_DUMP;
-	} else if (p == criu_restore_pid) {
-		np = "restore";
-		ep = CS_RESTORE;
-	} else
-		np = "???";
-
-	cp = (cp == pidstr1) ? pidstr2 : pidstr1;
-	snprintf(cp, sizeof pidstr1, "%s[%s %d]", pid ? "" : ep, np, p);
-	return cp;
-}
-
-void pipe_safe(int pipefd[2])
-{
-	if (pipe(pipefd) == -1)
-		die("pipe: %p", pipefd);
-}
-
-pid_t fork_safe(void)
-{
-	pid_t pid;
-
-	if ((pid = fork()) == -1)
-		die("fork: pid=%d", pid);
-	max_forks++;
-	return pid;
-}
-
-void signal_safe(int signum, sighandler_t handler)
-{
-	if (signal(signum, handler) == SIG_ERR)
-		die("signal: signum=%d", signum);
-}
-
-int open_safe(char *pathname, int flags)
-{
-	int fd;
-
-	if ((fd = open(pathname, flags, 0777)) == -1)
-		die("open: pathname=%s", pathname);
-	return fd;
-}
-
-void close_safe(int fd)
-{
-	if (close(fd) == -1)
-		die("close: fd=%d", fd);
-}
-
-void write_safe(int fd, char *buf, int count)
-{
-	if (write(fd, buf, count) != count) {
-		die("write: fd=%d buf=\"%s\" count=%d errno=%d",
-			fd, buf, count, errno);
-	}
-}
-
-int read_safe(int fd, char *buf, int count)
-{
-	int n;
-
-	if ((n = read(fd, buf, count)) < 0)
-		die("read: fd=%d count=%d", fd, count);
-	buf[n] = '\0';
-	return n;
-}
-
-int dup_safe(int oldfd)
-{
-	int newfd;
-
-	if ((newfd = dup(oldfd)) == -1)
-		die("dup: oldfd=%d", oldfd);
-	return newfd;
-}
-
-int dup2_safe(int oldfd, int newfd)
-{
-	if (dup2(oldfd, newfd) != newfd)
-		die("dup2: oldfd=%d newfd=%d", oldfd, newfd);
-	return newfd;
-}
-
-void move_fd(int oldfd, int newfd)
-{
-	if (oldfd != newfd) {
-		dup2_safe(oldfd, newfd);
-		close_safe(oldfd);
-	}
-}
-
-void mkdir_safe(char *dirname, int mode)
-{
-	if (mkdir(dirname, mode) == -1 && errno != EEXIST)
-		die("mkdir dirname=%s mode=0x%x\n", dirname, mode);
-}
-
-void unlink_safe(char *pathname)
-{
-	if (unlink(pathname) == -1 && errno != ENOENT) {
-		die("unlink: pathname=%s\n", pathname);
-	}
-}
-
-void execv_safe(char *path, char *argv[], int ls)
-{
-	int i;
-	struct timespec req = { 0, 1000000 };
-
-	if (!qflag) {
-		printf("\n%s ", who(0));
-		for (i = 0; argv[i] != NULL; i++)
-			printf("%s ", argv[i]);
-		printf("\n");
-	}
-
-	/* give parent a chance to wait for us */
-	while (nanosleep(&req, NULL))
-		;
-
-	if (vflag && ls)
-		ls_proc_fd(-1);
-
-	execv(path, argv);
-	die("execv: path=%s", path);
-}
-
-pid_t waitpid_safe(pid_t pid, int *status, int options, int id)
-{
-	pid_t p;
-
-	p = waitpid(pid, status, options);
-	if (p == -1)
-		fprintf(stderr, "waitpid pid=%d id=%d %m\n", pid, id);
-	return p;
-}
-
-void prctl_safe(int option, ulong arg2, ulong arg3, ulong arg4, ulong arg5)
-{
-	if (prctl(option, arg2, arg3, arg4, arg5) == -1)
-		die("prctl: option=0x%x", option);
-}
diff --git a/test/rpc/.gitignore b/test/rpc/.gitignore
deleted file mode 100644
index 75fca39..0000000
--- a/test/rpc/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-rpc.pb-c.*
-*_pb2.py
-test-c
diff --git a/test/rpc/Makefile b/test/rpc/Makefile
deleted file mode 100644
index 88b9f36..0000000
--- a/test/rpc/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-all: test-c rpc_pb2.py criu
-.PHONY: all
-
-CFLAGS += -g -Werror -Wall -I.
-LDFLAGS += -lprotobuf-c
-
-run: all
-	mkdir -p build
-	chmod a+rwx build
-	sudo -g '#1000' -u '#1000' ./run.sh
-
-criu: ../../criu/criu
-	cp ../../criu/criu $@
-	chmod u+s $@
-
-test-c: rpc.pb-c.o test-c.o
-
-test-c.o: test-c.c rpc.pb-c.c
-
-rpc_pb2.py: rpc.proto
-	protoc --proto_path=. --python_out=. rpc.proto
-
-rpc.pb-c.c: rpc.proto
-	protoc-c --proto_path=. --c_out=. rpc.proto
-
-clean:
-	rm -rf build rpc.pb-c.o test-c.o test-c rpc.pb-c.c rpc.pb-c.h rpc_pb2.py rpc_pb2.pyc criu
-.PHONY: clean
diff --git a/test/rpc/errno.py b/test/rpc/errno.py
deleted file mode 100755
index 666dfff..0000000
--- a/test/rpc/errno.py
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/usr/bin/python
-# Test criu errno
-
-import socket, os, imp, sys, errno
-import rpc_pb2 as rpc
-import argparse
-
-parser = argparse.ArgumentParser(description="Test errno reported by CRIU RPC")
-parser.add_argument('socket', type = str, help = "CRIU service socket")
-parser.add_argument('dir', type = str, help = "Directory where CRIU images should be placed")
-
-args = vars(parser.parse_args())
-
-# Prepare dir for images
-class test:
-	def __init__(self):
-		self.imgs_fd = os.open(args['dir'], os.O_DIRECTORY)
-		self.s = -1
-		self._MAX_MSG_SIZE = 1024
-
-	def connect(self):
-		self.s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
-		self.s.connect(args['socket'])
-
-	def get_base_req(self):
-		req			= rpc.criu_req()
-		req.opts.log_level	= 4
-		req.opts.images_dir_fd	= self.imgs_fd
-		return req
-
-	def send_req(self, req):
-		self.connect()
-		self.s.send(req.SerializeToString())
-
-	def recv_resp(self):
-		resp = rpc.criu_resp()
-		resp.ParseFromString(self.s.recv(self._MAX_MSG_SIZE))
-		return resp
-
-	def check_resp(self, resp, typ, err):
-		if resp.type != typ:
-			raise Exception('Unexpected responce type ' + str(resp.type))
-
-		if resp.success:
-			raise Exception('Unexpected success = True')
-
-		if err and resp.cr_errno != err:
-			raise Exception('Unexpected cr_errno ' + str(resp.cr_errno))
-
-	def no_process(self):
-		print 'Try to dump unexisting process'
-		# Get pid of non-existing process.
-		# Suppose max_pid is not taken by any process.
-		with open("/proc/sys/kernel/pid_max", "r") as f:
-			pid = int(f.readline())
-			try:
-				os.kill(pid, 0)
-			except OSError:
-				pass
-			else:
-				raise Exception('max pid is taken')
-
-		# Ask criu to dump non-existing process.
-		req = self.get_base_req()
-		req.type = rpc.DUMP
-		req.opts.pid = pid
-
-		self.send_req(req)
-		resp = self.recv_resp()
-
-		self.check_resp(resp, rpc.DUMP, errno.ESRCH)
-
-		print 'Success'
-
-	def process_exists(self):
-		print 'Try to restore process which pid is already taken by other process'
-
-		# Perform self-dump
-		req = self.get_base_req()
-		req.type		= rpc.DUMP
-		req.opts.leave_running	= True
-
-		self.send_req(req)
-		resp = self.recv_resp()
-
-		if resp.success != True:
-			raise Exception('Self-dump failed')
-
-		# Ask to restore process from images of ourselves
-		req = self.get_base_req()
-		req.type = rpc.RESTORE
-
-		self.send_req(req)
-		resp = self.recv_resp()
-
-		self.check_resp(resp, rpc.RESTORE, errno.EEXIST)
-
-		print 'Success'
-
-	def bad_options(self):
-		print 'Try to send criu invalid opts'
-
-		# Subdirs are not allowed in log_file
-		req = self.get_base_req()
-		req.type = rpc.DUMP
-		req.opts.log_file = "../file.log"
-
-		self.send_req(req)
-		resp = self.recv_resp()
-
-		self.check_resp(resp, rpc.DUMP, errno.EBADRQC)
-
-		print 'Success'
-
-	def bad_request(self):
-		print 'Try to send criu invalid request type'
-
-		req = self.get_base_req()
-		req.type = rpc.NOTIFY
-
-		self.send_req(req)
-		resp = self.recv_resp()
-
-		self.check_resp(resp, rpc.EMPTY, None)
-
-		print 'Success'
-
-	def run(self):
-		self.no_process()
-		self.process_exists()
-		self.bad_options()
-		self.bad_request()
-
-t = test()
-t.run()
diff --git a/test/rpc/loop.sh b/test/rpc/loop.sh
deleted file mode 100755
index 0ab34ce..0000000
--- a/test/rpc/loop.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-while :; do
-	sleep 1
-done
diff --git a/test/rpc/ps_test.py b/test/rpc/ps_test.py
deleted file mode 100755
index 82e5a50..0000000
--- a/test/rpc/ps_test.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/python
-
-import socket, os, imp, sys, errno
-import rpc_pb2 as rpc
-import argparse
-
-parser = argparse.ArgumentParser(description="Test page-server using CRIU RPC")
-parser.add_argument('socket', type = str, help = "CRIU service socket")
-parser.add_argument('dir', type = str, help = "Directory where CRIU images should be placed")
-
-args = vars(parser.parse_args())
-
-# Connect to service socket
-s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
-s.connect(args['socket'])
-
-# Start page-server
-print 'Starting page-server'
-req			= rpc.criu_req()
-req.type		= rpc.PAGE_SERVER
-req.opts.log_file	= 'page-server.log'
-req.opts.log_level	= 4
-req.opts.images_dir_fd	= os.open(args['dir'], os.O_DIRECTORY)
-
-s.send(req.SerializeToString())
-
-resp	= rpc.criu_resp()
-MAX_MSG_SIZE = 1024
-resp.ParseFromString(s.recv(MAX_MSG_SIZE))
-
-if resp.type != rpc.PAGE_SERVER:
-	print 'Unexpected msg type'
-	sys.exit(1)
-else:
-	if resp.success:
-		# check if pid even exists
-		try:
-			os.kill(resp.ps.pid, 0)
-		except OSError as err:
-			if err.errno == errno.ESRCH:
-				print 'No process with page-server pid %d' %(resp.ps.pid)
-			else:
-				print 'Can\'t check that process %d exists' %(resp.ps.pid)
-				sys.exit(1)
-		print 'Success, page-server pid %d started on port %u' %(resp.ps.pid, resp.ps.port)
-	else:
-		print 'Failed to start page-server'
-		sys.exit(1)
-
-
-# Perform self-dump
-print 'Dumping myself using page-server'
-req.type		= rpc.DUMP
-req.opts.ps.port	= resp.ps.port
-req.opts.log_file	= 'dump.log'
-req.opts.leave_running	= True
-
-s.close()
-s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
-s.connect(args['socket'])
-s.send(req.SerializeToString())
-
-resp.ParseFromString(s.recv(MAX_MSG_SIZE))
-
-if resp.type != rpc.DUMP:
-	print 'Unexpected msg type'
-	sys.exit(1)
-else:
-	if resp.success:
-		print 'Success'
-	else:
-		print 'Fail'
-		sys.exit(1)
diff --git a/test/rpc/restore-loop.py b/test/rpc/restore-loop.py
deleted file mode 100755
index 70cb64e..0000000
--- a/test/rpc/restore-loop.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/python
-
-import socket, os, imp, sys
-import rpc_pb2 as rpc
-import argparse
-
-parser = argparse.ArgumentParser(description="Test ability to restore a process from images using CRIU RPC")
-parser.add_argument('socket', type = str, help = "CRIU service socket")
-parser.add_argument('dir', type = str, help = "Directory where CRIU images could be found")
-
-args = vars(parser.parse_args())
-
-# Connect to service socket
-s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
-s.connect(args['socket'])
-
-# Create criu msg, set it's type to dump request
-# and set dump options. Checkout more options in protobuf/rpc.proto
-req			= rpc.criu_req()
-req.type		= rpc.RESTORE
-req.opts.images_dir_fd	= os.open(args['dir'], os.O_DIRECTORY)
-
-# Send request
-s.send(req.SerializeToString())
-
-# Recv response
-resp		= rpc.criu_resp()
-MAX_MSG_SIZE	= 1024
-resp.ParseFromString(s.recv(MAX_MSG_SIZE))
-
-if resp.type != rpc.RESTORE:
-	print 'Unexpected msg type'
-	sys.exit(-1)
-else:
-	if resp.success:
-		print 'Restore success'
-	else:
-		print 'Restore fail'
-		sys.exit(-1)
-	print "PID of the restored program is %d\n" %(resp.restore.pid)
diff --git a/test/rpc/rpc.proto b/test/rpc/rpc.proto
deleted file mode 120000
index bc0b0df..0000000
--- a/test/rpc/rpc.proto
+++ /dev/null
@@ -1 +0,0 @@
-../../protobuf/rpc.proto
\ No newline at end of file
diff --git a/test/rpc/run.sh b/test/rpc/run.sh
deleted file mode 100755
index ed99add..0000000
--- a/test/rpc/run.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/bin/bash
-
-set -e
-
-CRIU=./criu
-
-export PROTODIR=`readlink -f "${PWD}/../../protobuf"`
-
-echo $PROTODIR
-
-function title_print {
-	echo -e "\n**************************************************"
-	echo -e "\t\t"$1
-	echo -e "**************************************************\n"
-
-}
-
-function start_server {
-	title_print "Start service server"
-	${CRIU} service -v4 -W build -o service.log --address criu_service.socket -d --pidfile pidfile
-}
-
-function stop_server {
-	title_print "Shutdown service server"
-	kill -SIGTERM $(cat build/pidfile)
-	unlink build/pidfile
-}
-
-function test_c {
-	mkdir -p build/imgs_c
-
-	title_print "Run test-c"
-	setsid ./test-c build/criu_service.socket build/imgs_c < /dev/null &>> build/output_c
-
-	title_print "Restore test-c"
-	${CRIU} restore -v4 -o restore-c.log -D build/imgs_c
-}
-
-function test_py {
-	mkdir -p build/imgs_py
-
-	title_print "Run test-py"
-	setsid ./test.py build/criu_service.socket build/imgs_py < /dev/null &>> build/output_py
-
-	title_print "Restore test-py"
-	${CRIU} restore -v4 -o restore-py.log -D build/imgs_py
-}
-
-function test_restore_loop {
-	mkdir -p build/imgs_loop
-
-	title_print "Run loop.sh"
-	setsid ./loop.sh < /dev/null &> build/loop.log &
-	P=${!}
-	echo "pid ${P}"
-
-	title_print "Dump loop.sh"
-	${CRIU} dump -v4 -o dump-loop.log -D build/imgs_loop -t ${P}
-
-	title_print "Run restore-loop"
-	./restore-loop.py build/criu_service.socket build/imgs_loop
-	kill -SIGTERM ${P}
-}
-
-function test_ps {
-	mkdir -p build/imgs_ps
-
-	title_print "Run ps_test"
-	setsid ./ps_test.py build/criu_service.socket build/imgs_ps < /dev/null &>> build/output_ps
-}
-
-function test_errno {
-	mkdir -p build/imgs_errno
-
-	title_print "Run cr_errno test"
-	setsid ./errno.py build/criu_service.socket build/imgs_errno < /dev/null &>> build/output_errno
-}
-
-trap 'echo "FAIL"; stop_server' EXIT
-
-start_server
-
-test_c
-test_py
-test_restore_loop
-test_ps
-test_errno
-
-stop_server
-
-trap 'echo "Success"' EXIT
diff --git a/test/rpc/test-c.c b/test/rpc/test-c.c
deleted file mode 100644
index 490a07a..0000000
--- a/test/rpc/test-c.c
+++ /dev/null
@@ -1,170 +0,0 @@
-#include "rpc.pb-c.h"
-#include <stdlib.h>
-#include <stdbool.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/fcntl.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <unistd.h>
-
-#define MAX_MSG_SIZE 1024
-
-static CriuResp *recv_resp(int socket_fd)
-{
-	unsigned char buf[MAX_MSG_SIZE];
-	int len;
-	CriuResp *msg = 0;
-
-	len = read(socket_fd, buf, MAX_MSG_SIZE);
-	if (len == -1) {
-		perror("Can't read response");
-		return NULL;
-	}
-
-	msg = criu_resp__unpack(NULL, len, buf);
-	if (!msg) {
-		perror("Failed unpacking response");
-		return NULL;
-	}
-
-	return msg;
-}
-
-static int send_req(int socket_fd, CriuReq *req)
-{
-	unsigned char buf[MAX_MSG_SIZE];
-	int len;
-
-	len = criu_req__get_packed_size(req);
-
-	if (criu_req__pack(req, buf) != len) {
-		perror("Failed packing request");
-		return -1;
-	}
-
-	if (write(socket_fd, buf, len)  == -1) {
-		perror("Can't send request");
-		return -1;
-	}
-
-	return 0;
-}
-
-int main(int argc, char *argv[])
-{
-	CriuReq req		= CRIU_REQ__INIT;
-	CriuResp *resp		= NULL;
-	int fd, dir_fd;
-	int ret = 0;
-	struct sockaddr_un addr;
-	socklen_t addr_len;
-
-	if (argc != 3) {
-		fprintf(stderr, "Usage: test-c criu-service.socket imgs_dir");
-		return -1;
-	}
-
-	/*
-	 * Open a directory, in which criu will
-	 * put images
-	 */
-
-	puts(argv[2]);
-	dir_fd = open(argv[2], O_DIRECTORY);
-	if (dir_fd == -1) {
-		perror("Can't open imgs dir");
-		return -1;
-	}
-
-	/*
-	 * Set "DUMP" type of request.
-	 * Allocate CriuDumpReq.
-	 */
-	req.type			= CRIU_REQ_TYPE__DUMP;
-	req.opts			= malloc(sizeof(CriuOpts));
-	if (!req.opts) {
-			perror("Can't allocate memory for dump request");
-			return -1;
-	}
-
-	criu_opts__init(req.opts);
-
-	/*
-	 * Set dump options.
-	 * Checkout more in protobuf/rpc.proto.
-	 */
-	req.opts->has_leave_running	= true;
-	req.opts->leave_running		= true;
-	req.opts->images_dir_fd		= dir_fd;
-	req.opts->has_log_level		= true;
-	req.opts->log_level		= 4;
-
-	/*
-	 * Connect to service socket
-	 */
-	fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
-	if (fd == -1) {
-		perror("Can't create socket");
-		return -1;
-	}
-
-	memset(&addr, 0, sizeof(addr));
-	addr.sun_family = AF_LOCAL;
-
-	strcpy(addr.sun_path, argv[1]);
-
-	addr_len = strlen(addr.sun_path) + sizeof(addr.sun_family);
-
-	ret = connect(fd, (struct sockaddr *) &addr, addr_len);
-	if (ret == -1) {
-		perror("Cant connect to socket");
-		goto exit;
-	}
-
-	/*
-	 * Send request
-	 */
-	ret = send_req(fd, &req);
-	if (ret == -1) {
-		perror("Can't send request");
-		goto exit;
-	}
-
-	/*
-	 * Recv response
-	 */
-	resp = recv_resp(fd);
-	if (!resp) {
-		perror("Can't recv response");
-		ret = -1;
-		goto exit;
-	}
-
-	if (resp->type != CRIU_REQ_TYPE__DUMP) {
-		perror("Unexpected response type");
-		ret = -1;
-		goto exit;
-	}
-
-	/*
-	 * Check response.
-	 */
-	if (resp->success)
-		puts("Success");
-	else {
-		puts("Fail");
-		ret = -1;
-		goto exit;
-	}
-
-	if (resp->dump->has_restored && resp->dump->restored)
-		puts("Restored");
-
-exit:
-	close(fd);
-	close(dir_fd);
-	if (resp)
-		criu_resp__free_unpacked(resp, NULL);
-	return ret;
-}
diff --git a/test/rpc/test.py b/test/rpc/test.py
deleted file mode 100755
index 7154c00..0000000
--- a/test/rpc/test.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/python
-
-import socket, os, imp, sys
-import rpc_pb2 as rpc
-import argparse
-
-parser = argparse.ArgumentParser(description="Test dump/restore using CRIU RPC")
-parser.add_argument('socket', type = str, help = "CRIU service socket")
-parser.add_argument('dir', type = str, help = "Directory where CRIU images should be placed")
-
-args = vars(parser.parse_args())
-
-# Connect to service socket
-s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
-s.connect(args['socket'])
-
-# Create criu msg, set it's type to dump request
-# and set dump options. Checkout more options in protobuf/rpc.proto
-req			= rpc.criu_req()
-req.type		= rpc.DUMP
-req.opts.leave_running	= True
-req.opts.log_level	= 4
-req.opts.images_dir_fd	= os.open(args['dir'], os.O_DIRECTORY)
-
-# Send request
-s.send(req.SerializeToString())
-
-# Recv response
-resp		= rpc.criu_resp()
-MAX_MSG_SIZE	= 1024
-resp.ParseFromString(s.recv(MAX_MSG_SIZE))
-
-if resp.type != rpc.DUMP:
-	print 'Unexpected msg type'
-	sys.exit(-1)
-else:
-	if resp.success:
-		print 'Success'
-	else:
-		print 'Fail'
-		sys.exit(-1)
-
-	if resp.dump.restored:
-		print 'Restored'
diff --git a/test/security/Makefile b/test/security/Makefile
deleted file mode 100644
index 6eaece1..0000000
--- a/test/security/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-DIR	:= $(shell pwd)/data
-LOOP	:= $(DIR)/loop.sh
-PIDFILE := $(DIR)/loop.pid
-IMGS	:= $(DIR)/imgs
-CRIU	:= $(DIR)/criu
-
-ROOT	:=root
-USR1	:=criu-test-user1
-USR2	:=criu-test-user2
-
-export DIR LOOP PIDFILE IMGS CRIU ROOT USR1 USR2
-
-run: testdir users
-	./run.sh
-
-testdir: ../../criu/criu
-	mkdir -p $(DIR)
-	mkdir -p $(IMGS)
-	cp ../../criu/criu $(CRIU)
-	chmod u+s $(CRIU)
-	cp loop.sh $(LOOP)
-	chmod 777 $(DIR)
-
-users:
-	-userdel -f $(USR1)
-	-userdel -f $(USR2)
-	useradd -M -U $(USR1)
-	useradd -M -U $(USR2)
-	usermod -a -G $(USR2) $(USR1)
-
-clean:
-	rm -rf $(DIR)
-	-userdel -f $(USR1)
-	-userdel -f $(USR2)
diff --git a/test/security/loop.sh b/test/security/loop.sh
deleted file mode 100755
index 0a01053..0000000
--- a/test/security/loop.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-echo $$ > $1.int
-mv $1.int $1
-
-if [ "$2" == "--chgrp" ]; then
-	grps=( $(groups) )
-	newgrp ${grps[2]}
-fi
-
-while :; do
-	sleep 1
-done
diff --git a/test/security/run.sh b/test/security/run.sh
deleted file mode 100755
index e75ab44..0000000
--- a/test/security/run.sh
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/bin/bash
-
-set -x
-
-PID=
-
-function run_as {
-	echo "== Run ${LOOP} as $1"
-	echo ${PIDFILE}
-	rm -f ${PIDFILE}
-	su $1 -c "setsid ${LOOP} ${PIDFILE} $2 < /dev/null &> /dev/null &"
-	for i in `seq 100`; do
-		test -f ${PIDFILE} && break
-		sleep 1
-	done
-	PID=`cat ${PIDFILE}`
-	echo ${PID}
-}
-
-function dump_as {
-	test -d ${IMGS} && rm -rf ${IMGS}
-	mkdir -p ${IMGS}
-	echo "== Dump ${PID} as $@"
-	su $@ -c "${CRIU} dump --tree ${PID} --images-dir ${IMGS}"
-	return $?
-}
-
-function rstr_as {
-	echo "== Restore ${IMGS} as $@"
-	su $@ -c "${CRIU} restore --images-dir ${IMGS} --restore-detached"
-	return $?
-}
-
-function result {
-	local BGRED='\033[41m'
-	local BGGREEN='\033[42m'
-	local NORMAL=$(tput sgr0)
-
-	if [ $1 -ne 0 ]; then
-		echo -e "${BGRED}FAIL${NORMAL}"
-		exit 1
-	else
-		echo -e "${BGGREEN}PASS${NORMAL}"
-	fi
-}
-
-function test_root {
-	echo "==== Check that non-root can't dump/restore process owned by root"
-
-	run_as  ${ROOT}
-
-	dump_as ${USR1} ; result $((!$?))
-	dump_as ${ROOT} ; result $(($?))
-
-	rstr_as ${USR1} ; result $((!$?))
-	rstr_as ${ROOT} ; result $(($?))
-
-	kill -SIGKILL ${PID}
-}
-
-function test_other {
-	echo "==== Check that user2 can't dump/restore process owned by user1"
-
-	run_as  ${USR1}
-
-	dump_as ${USR2} ; result $((!$?))
-	dump_as ${USR1} ; result $(($?))
-
-	rstr_as ${USR2} ; result $((!$?))
-	rstr_as ${USR1} ; result $(($?))
-
-	kill -SIGKILL ${PID}
-}
-
-function test_own {
-	echo "==== Check that user1 can dump/restore his own process that changes it's gid to one from groups"
-
-	run_as  ${USR1} "--chgrp"
-
-	dump_as ${USR1} ; result $(($?))
-
-	rstr_as ${USR1} ; result $(($?))
-
-	kill -SIGKILL ${PID}
-}
-
-test_root
-test_other
-test_own
diff --git a/test/socketpairs/Makefile b/test/socketpairs/Makefile
deleted file mode 100644
index dbb152c..0000000
--- a/test/socketpairs/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-CFLAGS += -Wall
-socketpair: socketpair.c
-clean:
-	rm -f socketpair
-run: socketpair
-	./socketpair  &&		\
-	./socketpair -v &&		\
-	./socketpair -m4 &&		\
-	true
diff --git a/test/socketpairs/socketpair.c b/test/socketpairs/socketpair.c
deleted file mode 100644
index 900c3d6..0000000
--- a/test/socketpairs/socketpair.c
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- * A simple demo/test program using criu's --inherit-fd command line
- * option to restore a process with an external unix socket.
- * Extending inherit's logic to unix sockets created by socketpair(..) syscall.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <time.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/wait.h>
-#include <sys/prctl.h>
-#include <sys/socket.h>
-
-typedef void (*sighandler_t)(int);
-typedef unsigned long ulong;
-
-/* colors */
-#define CS_PARENT 		"\033[00;32m"
-#define CS_CHILD 		"\033[00;33m"
-#define CS_DUMP 		"\033[00;34m"
-#define CS_RESTORE 		"\033[00;35m"
-#define CE			"\033[0m"
-
-#define die(fmt, ...) do { \
-	fprintf(stderr, fmt ": %m\n", __VA_ARGS__); \
-	if (getpid() == parent_pid) { \
-		(void)kill(0, 9); \
-		exit(1); \
-	} \
-	_exit(1); \
-} while (0)
-
-#define READ_FD		0	/* pipe read fd */
-#define WRITE_FD	1	/* pipe write fd */
-#define CLASH_FD	3	/* force inherit fd clash */
-
-#define MAX_FORKS	3	/* child, checkpoint, restore */
-
-#define CRIU_BINARY		"../../criu/criu"
-#define IMG_DIR			"images"
-#define DUMP_LOG_FILE		"dump.log"
-#define RESTORE_LOG_FILE	"restore.log"
-#define RESTORE_PID_FILE	"restore.pid"
-#define INHERIT_FD_OPTION	"--inherit-fd"
-#define OLD_LOG_FILE		"/tmp/oldlog"
-#define NEW_LOG_FILE		"/tmp/newlog"
-
-/*
- * Command line options (see usage()).
- */
-
-char *cli_flags = "hm:nv";
-int max_msgs = 10;
-int vflag;
-int nflag;
-
-char pid_number[8];
-char inh_unixsk_opt[16];
-char inh_unixsk_arg[64];
-char external_sk_ino[32];
-
-char *dump_argv[] = {
-	"criu", "dump",
-	"-D", IMG_DIR, "-o", DUMP_LOG_FILE,
-	"-v4",
-	external_sk_ino,
-	"-t", pid_number,
-	NULL
-};
-
-char *restore_argv[] = {
-	"criu", "restore", "-d",
-	"-D", IMG_DIR, "-o", RESTORE_LOG_FILE,
-	"--pidfile", RESTORE_PID_FILE,
-	"-v4", "-x",
-	inh_unixsk_opt, inh_unixsk_arg,
-	NULL
-};
-
-int max_forks;
-int parent_pid;
-int child_pid;
-int criu_dump_pid;
-int criu_restore_pid;
-
-/* prototypes */
-void chld_handler(int signum);
-int parent(int *socketfd, const char *ino_child_sk);
-int child(int *socketfd, int dupfd, int newfd);
-void checkpoint_child(int child_pid, int *old_socket_namefd);
-void restore_child(int *new_socketfd, const char *old_socket_name);
-void write_to_fd(int fd, char *name, int i, int newline);
-void ls_proc_fd(int fd);
-char *socket_name(int fd);
-ino_t socket_inode(int fd);
-char *who(pid_t pid);
-void socketpair_safe(int socketfd[2]);
-pid_t fork_safe(void);
-void signal_safe(int signum, sighandler_t handler);
-int open_safe(char *pathname, int flags);
-void close_safe(int fd);
-void write_safe(int fd, char *buf, int count);
-int read_safe(int fd, char *buf, int count);
-int dup_safe(int oldfd);
-void move_fd(int oldfd, int newfd);
-void mkdir_safe(char *dirname, int mode);
-void unlink_safe(char *pathname);
-void execv_safe(char *path, char *argv[], int ls);
-pid_t waitpid_safe(pid_t pid, int *status, int options, int id);
-void prctl_safe(int option, ulong arg2, ulong arg3, ulong arg4, ulong arg5);
-int dup2_safe(int oldfd, int newfd);
-
-void usage(char *cmd)
-{
-	printf("Usage: %s [%s]\n", cmd, cli_flags);
-	printf("-h\tprint this help and exit\n");
-	printf("-m\tcount of send messages (by default 10 will send from child) \n");
-	printf("-n\tdo not use the %s option\n", INHERIT_FD_OPTION);
-	printf("-v\tverbose mode (list contents of /proc/<pid>/fd)\n");
-}
-
-int main(int argc, char *argv[])
-{
-	int ret;
-	int opt;
-	int socketfd[2];
-
-	while ((opt = getopt(argc, argv, cli_flags)) != -1) {
-		switch (opt) {
-		case 'h':
-			usage(argv[0]);
-			return 0;
-		case 'm':
-			max_msgs = atoi(optarg);
-			break;
-		case 'n':
-			nflag++;
-			break;
-		case 'v':
-			vflag++;
-			break;
-		case '?':
-			if ('m' == optopt)
-				fprintf (stderr, "Option -%c requires an argument.\n", optopt);
-			else
-			fprintf (
-				stderr,
-				"Unknown option character `\\x%x'.\n",
-				optopt);
-			return 1;
-		default:
-			usage(argv[0]);
-			return 1;
-		}
-	}
-
-	setbuf(stdout, NULL);
-	setbuf(stderr, NULL);
-	mkdir_safe(IMG_DIR, 0700);
-
-	socketpair_safe(socketfd);
-	child_pid = fork_safe();
-	if (child_pid > 0) {
-		parent_pid = getpid();
-
-		signal_safe(SIGCHLD, chld_handler);
-		prctl_safe(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
-
-		snprintf(external_sk_ino, sizeof(external_sk_ino), "--ext-unix-sk=%u",
-			(unsigned int)socket_inode(socketfd[WRITE_FD]));
-
-		char unix_sk_ino[32] = {0};
-		strcpy(unix_sk_ino, socket_name(socketfd[WRITE_FD]));
-		close_safe(socketfd[WRITE_FD]);
-		ret = parent(socketfd, unix_sk_ino);
-	} else {
-		/* child */
-		int dupfd = -1;
-		int openfd = -1;
-		int logfd;
-
-		child_pid = getpid();
-
-		close_safe(socketfd[READ_FD]);
-		setsid();
-		logfd = open_safe(OLD_LOG_FILE, O_WRONLY | O_APPEND | O_CREAT);
-		dup2_safe(logfd, 1);
-		dup2_safe(logfd, 2);
-		close(logfd);
-		close(0);
-
-		ret = child(socketfd, dupfd, openfd);
-	}
-
-	return ret;
-}
-
-/*
- * Parent reads message from its pipe with the child.
- * After a couple of messages, it checkpoints the child
- * which causes the child to exit.  Parent then creates
- * a new pipe and restores the child.
- */
-int parent(int *socketfd, const char *ino_child_sk)
-{
-	char buf[32];
-	int nread;
-
-	nread = 0;
-	while (max_forks <= MAX_FORKS) {
-		if (read_safe(socketfd[READ_FD], buf, sizeof buf) == 0)
-			continue;
-		nread++;
-		if (vflag && nread == 1)
-			ls_proc_fd(-1);
-
-		printf(
-			"%s read %s from %s\n",
-			who(0), buf,
-			socket_name(socketfd[READ_FD]));
-
-
-		if (nread == (max_msgs / 2)) {
-			checkpoint_child(child_pid, socketfd);
-
-			if (!nflag) {
-				close_safe(socketfd[READ_FD]);
-
-				/* create a new one */
-				printf("%s creating a new socket\n", who(0));
-				socketpair_safe(socketfd);
-			}
-
-			restore_child(socketfd, ino_child_sk);
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Child sends a total of max_messages messages to its
- * parent, half before checkpoint and half after restore.
- */
-int child(int *socketfd, int dupfd, int openfd)
-{
-	int i;
-	int fd;
-	int num_wfds;
-	struct timespec req = { 1, 0 };
-
-	/*
-	 * Count the number of pipe descriptors we'll be
-	 * writing to.  At least 1 (for socketfd[WRITE_FD])
-	 * and at most 3.
-	 */
-	num_wfds = 1;
-	if (dupfd >= 0)
-		num_wfds++;
-	if (openfd >= 0)
-		num_wfds++;
-
-	for (i = 0; i < max_msgs; i++) {
-		/* print first time and after checkpoint */
-		if (vflag && (i == 0 || i == (max_msgs / 2)))
-			ls_proc_fd(-1);
-
-		switch (i % num_wfds) {
-			case 0: fd = socketfd[WRITE_FD]; break;
-			case 1: fd = openfd; break;
-			case 2: fd = openfd; break;
-		}
-
-		write_to_fd(fd, socket_name(socketfd[WRITE_FD]), i+1, 0);
-		/*
-		 * Since sleep will be interrupted by C/R, make sure
-		 * to sleep an entire second to minimize the chance of
-		 * writing before criu restore has exited.  If criu is
-		 * still around and we write to a broken pipe, we'll be
-		 * killed but SIGCHLD will be delivered to criu instead
-		 * of parent.
-		 */
-		while (nanosleep(&req, NULL))
-			;
-		printf("\n");
-	}
-
-	return 0;
-}
-
-void chld_handler(int signum)
-{
-	int status;
-	pid_t pid;
-
-	pid = waitpid_safe(-1, &status, WNOHANG, 1);
-	if (WIFEXITED(status))
-		status = WEXITSTATUS(status);
-	if (pid == child_pid) {
-		printf("%s %s exited with status %d\n", who(0),
-			who(pid), status);
-		/* if child exited successfully, we're done */
-		if (status == 0)
-			exit(0);
-		/* checkpoint kills the child */
-		if (status != 9)
-			exit(status);
-	}
-}
-
-void checkpoint_child(int child_pid, int *socketfd)
-{
-	/* prepare -t <pid> */
-	snprintf(pid_number, sizeof pid_number, "%d", child_pid);
-
-	criu_dump_pid = fork_safe();
-	if (criu_dump_pid > 0) {
-		int status;
-		pid_t pid;
-
-		pid = waitpid_safe(criu_dump_pid, &status, 0, 2);
-		if (WIFEXITED(status))
-			status = WEXITSTATUS(status);
-		printf("%s %s exited with status %d\n", who(0),
-			who(pid), status);
-		if (status)
-			exit(status);
-	} else {
-		close(socketfd[READ_FD]);
-		criu_dump_pid = getpid();
-		execv_safe(CRIU_BINARY, dump_argv, 0);
-	}
-}
-
-void restore_child(int *new_socketfd, const char *old_sock_name)
-{
-	char buf[64];
-
-	criu_restore_pid = fork_safe();
-	if (criu_restore_pid > 0) {
-		int status;
-		pid_t pid;
-
-		if (!nflag)
-			close_safe(new_socketfd[WRITE_FD]);
-
-		pid = waitpid_safe(criu_restore_pid, &status, 0, 3);
-		if (WIFEXITED(status))
-			status = WEXITSTATUS(status);
-
-		printf("%s %s exited with status %d\n", who(0),
-			who(pid), status);
-
-		if (status)
-			exit(status);
-	} else {
-		criu_restore_pid = getpid();
-
-		if (!nflag) {
-			close_safe(new_socketfd[READ_FD]);
-			move_fd(new_socketfd[WRITE_FD], CLASH_FD);
-
-			/* --inherit-fd fd[CLASH_FD]:socket[xxxxxx] */
-			snprintf(inh_unixsk_opt, sizeof inh_unixsk_opt,
-				"%s", INHERIT_FD_OPTION);
-			snprintf(inh_unixsk_arg, sizeof inh_unixsk_arg, "fd[%d]:%s",
-				CLASH_FD, old_sock_name);
-
-			restore_argv[11] = inh_unixsk_opt;
-			restore_argv[13] = NULL;
-		} else
-			restore_argv[11] = NULL;
-
-		snprintf(buf, sizeof buf, "%s/%s", IMG_DIR, RESTORE_PID_FILE);
-		unlink_safe(buf);
-		execv_safe(CRIU_BINARY, restore_argv, 1);
-	}
-}
-
-void write_to_fd(int fd, char *name, int i, int newline)
-{
-	int n;
-	char buf[16];	/* fit "hello d\n" for small d */
-
-	n = snprintf(buf, sizeof buf, "hello %d", i);
-
-	printf("%s writing %s to %s via fd %d\n", who(0), buf, name, fd);
-
-	if (newline) {
-		buf[n++] = '\n';
-		buf[n] = '\0';
-	}
-	write_safe(fd, buf, strlen(buf));
-}
-
-void ls_proc_fd(int fd)
-{
-	char cmd[128];
-
-	if (fd == -1)
-		snprintf(cmd, sizeof cmd, "ls -l /proc/%d/fd", getpid());
-	else
-		snprintf(cmd, sizeof cmd, "ls -l /proc/%d/fd/%d", getpid(), fd);
-	printf("%s %s\n", who(0), cmd);
-	system(cmd);
-}
-
-char *socket_name(int fd)
-{
-	static char sock_name[64];
-	char path[64];
-
-	snprintf(path, sizeof path, "/proc/self/fd/%d", fd);
-	if (readlink(path, sock_name, sizeof sock_name) == -1)
-		die("readlink: path=%s", path);
-	return sock_name;
-}
-
-ino_t socket_inode(int fd)
-{
-         struct stat sbuf;
-
-         if (fstat(fd, &sbuf) == -1)
-                 die("fstat: fd=%i", fd);
-
-         return sbuf.st_ino;
-}
-
-/*
- * Use two buffers to support two calls to
- * this function in a printf argument list.
- */
-char *who(pid_t pid)
-{
-	static char pidstr1[64];
-	static char pidstr2[64];
-	static char *cp;
-	char *np;
-	char *ep;
-	int p;
-
-	p = pid ? pid : getpid();
-	if (p == parent_pid) {
-		np = "parent";
-		ep = CS_PARENT;
-	} else if (p == child_pid) {
-		np = "child";
-		ep = CS_CHILD;
-	} else if (p == criu_dump_pid) {
-		np = "dump";
-		ep = CS_DUMP;
-	} else if (p == criu_restore_pid) {
-		np = "restore";
-		ep = CS_RESTORE;
-	} else
-		np = "???";
-
-	cp = (cp == pidstr1) ? pidstr2 : pidstr1;
-	snprintf(cp, sizeof pidstr1, "%s[%s %d]", pid ? "" : ep, np, p);
-	return cp;
-}
-
-void socketpair_safe(int socketfd[2])
-{
-	if (socketpair(AF_UNIX, SOCK_STREAM, 0, socketfd) == -1)
-		die("socketpair %p", socketfd);
-}
-
-pid_t fork_safe(void)
-{
-	pid_t pid;
-
-	if ((pid = fork()) == -1)
-		die("fork: pid=%d", pid);
-	max_forks++;
-	return pid;
-}
-
-void signal_safe(int signum, sighandler_t handler)
-{
-	if (signal(signum, handler) == SIG_ERR)
-		die("signal: signum=%d", signum);
-}
-
-int open_safe(char *pathname, int flags)
-{
-	int fd;
-
-	if ((fd = open(pathname, flags, 0777)) == -1)
-		die("open: pathname=%s", pathname);
-	return fd;
-}
-
-void close_safe(int fd)
-{
-	if (close(fd) == -1)
-		die("close: fd=%d", fd);
-}
-
-void write_safe(int fd, char *buf, int count)
-{
-	if (write(fd, buf, count) != count) {
-		die("write: fd=%d buf=\"%s\" count=%d errno=%d",
-			fd, buf, count, errno);
-	}
-}
-
-int read_safe(int fd, char *buf, int count)
-{
-	int n;
-
-	if ((n = read(fd, buf, count)) < 0)
-		die("read: fd=%d count=%d", fd, count);
-	buf[n] = '\0';
-	return n;
-}
-
-int dup_safe(int oldfd)
-{
-	int newfd;
-
-	if ((newfd = dup(oldfd)) == -1)
-		die("dup: oldfd=%d", oldfd);
-	return newfd;
-}
-
-int dup2_safe(int oldfd, int newfd)
-{
-	if (dup2(oldfd, newfd) != newfd)
-		die("dup2: oldfd=%d newfd=%d", oldfd, newfd);
-	return newfd;
-}
-
-void move_fd(int oldfd, int newfd)
-{
-	if (oldfd != newfd) {
-		dup2_safe(oldfd, newfd);
-		close_safe(oldfd);
-	}
-}
-
-void mkdir_safe(char *dirname, int mode)
-{
-	if (mkdir(dirname, mode) == -1 && errno != EEXIST)
-		die("mkdir dirname=%s mode=0x%x\n", dirname, mode);
-}
-
-void unlink_safe(char *pathname)
-{
-	if (unlink(pathname) == -1 && errno != ENOENT) {
-		die("unlink: pathname=%s\n", pathname);
-	}
-}
-
-void execv_safe(char *path, char *argv[], int ls)
-{
-	int i;
-	struct timespec req = { 0, 1000000 };
-
-	printf("\n%s ", who(0));
-	for (i = 0; argv[i] != NULL; i++)
-		printf("%s ", argv[i]);
-	printf("\n");
-
-	/* give parent a chance to wait for us */
-	while (nanosleep(&req, NULL))
-		;
-
-	if (vflag && ls)
-		ls_proc_fd(-1);
-
-	execv(path, argv);
-	die("execv: path=%s", path);
-}
-
-pid_t waitpid_safe(pid_t pid, int *status, int options, int id)
-{
-	pid_t p;
-
-	p = waitpid(pid, status, options);
-	if (p == -1)
-		fprintf(stderr, "waitpid pid=%d id=%d %m\n", pid, id);
-	return p;
-}
-
-void prctl_safe(int option, ulong arg2, ulong arg3, ulong arg4, ulong arg5)
-{
-	if (prctl(option, arg2, arg3, arg4, arg5) == -1)
-		die("prctl: option=0x%x", option);
-}
diff --git a/test/tcp/Makefile b/test/tcp/Makefile
deleted file mode 100644
index 311d68b..0000000
--- a/test/tcp/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-OBJS=cln srv
-
-all: $(OBJS)
-.PHONY: all
-
-run: all
-	./run.sh
-
-clean:
-	rm -f $(OBJS)
-.PHONY: clean
diff --git a/test/tcp/cln.c b/test/tcp/cln.c
deleted file mode 100644
index 6275d37..0000000
--- a/test/tcp/cln.c
+++ /dev/null
@@ -1,122 +0,0 @@
-#include <sys/socket.h>
-#include <linux/types.h>
-#include <sys/types.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <signal.h>
-
-#define BUF_SIZE	(1024)
-
-static char rbuf[BUF_SIZE];
-static char buf[BUF_SIZE];
-
-static int check_buf(int sk, char *buf, int count)
-{
-	int rd, i;
-
-	printf("Checking for %d bytes\n", count);
-
-	rd = 0;
-	while (rd < count) {
-		int r;
-
-		r = read(sk, rbuf + rd, count - rd);
-		if (r == 0) {
-			printf("Unexpected EOF\n");
-			return 1;
-		}
-
-		if (r < 0) {
-			perror("Can't read buf");
-			return 1;
-		}
-
-		rd += r;
-	}
-
-	for (i = 0; i < count; i++)
-		if (buf[i] != rbuf[i]) {
-			printf("Mismatch on %d byte %d != %d\n",
-					i, (int)buf[i], (int)rbuf[i]);
-			return 1;
-		}
-
-	return 0;
-}
-
-static int serve_new_conn(int in_fd, int sk)
-{
-	printf("New connection\n");
-
-	while (1) {
-		int rd, wr;
-
-		rd = read(in_fd, buf, sizeof(buf));
-		if (rd == 0)
-			break;
-		if (rd < 0) {
-			perror("Can't read from infd");
-			return 1;
-		}
-
-		printf("Read %d bytes, sending to sock\n", rd);
-
-		wr = 0;
-		while (wr < rd) {
-			int w;
-
-			w = write(sk, buf + wr, rd - wr);
-			if (w <= 0) {
-				perror("Can't write to socket");
-				return 1;
-			}
-
-			if (check_buf(sk, buf + wr, w))
-				return 1;
-
-			wr += w;
-		}
-	}
-
-	printf("Done\n");
-	return 0;
-}
-
-int main(int argc, char **argv)
-{
-	int sk, port, ret;
-	struct sockaddr_in addr;
-
-	if (argc < 3) {
-		printf("Need addr, port and iters\n");
-		return -1;
-	}
-
-	sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-	if (sk < 0) {
-		perror("Can't create socket");
-		return -1;
-	}
-
-	port = atoi(argv[2]);
-	printf("Connecting to %s:%d\n", argv[1], port);
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	ret = inet_aton(argv[1], &addr.sin_addr);
-	if (ret < 0) {
-		perror("Can't convert addr");
-		return -1;
-	}
-	addr.sin_port = htons(port);
-
-	ret = connect(sk, (struct sockaddr *)&addr, sizeof(addr));
-	if (ret < 0) {
-		perror("Can't connect");
-		return -1;
-	}
-
-	return serve_new_conn(0, sk);
-}
diff --git a/test/tcp/run.sh b/test/tcp/run.sh
deleted file mode 100755
index 702879d..0000000
--- a/test/tcp/run.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-
-source ../env.sh || exit 1
-
-set -x
-
-PORT=12345
-CLN_PIPE="./clnt_pipe"
-SRV_LOG="./srv.log"
-CLN_LOG="./cln.log"
-DDIR="dump"
-
-TEXT=$(hexdump -C /dev/urandom | head -n 1)
-
-echo "Building services"
-
-make clean && make || { echo "Failed to build"; exit 1; }
-rm -rf ${DDIR} ${SRV_LOG} ${CLN_LOG} ${CLN_PIPE}
-mkdir ${DDIR}
-
-echo "Starting server"
-
-setsid ./srv ${PORT} > ${SRV_LOG} 2>&1 &
-SRV_PID=${!}
-
-echo "Starting pipe"
-mkfifo ${CLN_PIPE}
-
-echo "Starting client"
-./cln "127.0.0.1" ${PORT} < ${CLN_PIPE} > ${CLN_LOG} &
-CLN_PID=${!}
-
-exec 3>${CLN_PIPE}
-echo "Make it run"
-echo "${TEXT}" >&3
-
-function fail {
-	echo FAIL
-
-(	exec >&2
-
-	echo "$@"
-	kill -9 ${CLN_PID}
-	kill -9 ${SRV_PID}
-	echo ${CLN_LOG}:
-	cat ${CLN_LOG}
-)
-	exit 1
-}
-
-kill -s 0 ${CLN_PID} || fail "Client is dead"
-
-echo "Suspend server"
-${CRIU} dump -D ${DDIR} -o dump.log -t ${SRV_PID} --tcp-established -vvvv || fail "Fail to dump server"
-sleep 1
-echo "Resume server"
-${CRIU} restore -D ${DDIR} -o restore.log -d --tcp-established -vvvv --close 3 || fail "Fail to restore server"
-
-echo "Make client run again"
-echo "${TEXT}" >&3
-
-echo "Collect results"
-exec 3>&-
-wait ${CLN_PID} || fail "Client exits abruptly"
-kill -9 ${SRV_PID}
-
-echo PASS
diff --git a/test/tcp/srv.c b/test/tcp/srv.c
deleted file mode 100644
index 656cc01..0000000
--- a/test/tcp/srv.c
+++ /dev/null
@@ -1,112 +0,0 @@
-#include <sys/socket.h>
-#include <linux/types.h>
-#include <sys/types.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <signal.h>
-
-static int serve_new_conn(int sk)
-{
-	int rd, wr;
-	char buf[1024];
-
-	printf("New connection\n");
-
-	while (1) {
-		rd = read(sk, buf, sizeof(buf));
-		if (!rd)
-			break;
-
-		if (rd < 0) {
-			perror("Can't read socket");
-			return 1;
-		}
-
-		wr = 0;
-		while (wr < rd) {
-			int w;
-
-			w = write(sk, buf + wr, rd - wr);
-			if (w <= 0) {
-				perror("Can't write socket");
-				return 1;
-			}
-
-			wr += w;
-		}
-	}
-
-	printf("Done\n");
-	return 0;
-}
-
-int main(int argc, char **argv)
-{
-	int sk, port, ret;
-	struct sockaddr_in addr;
-
-	if (argc < 2) {
-		printf("Need port\n");
-		return -1;
-	}
-
-	/*
-	 * Let kids die themselves
-	 */
-
-	signal(SIGCHLD, SIG_IGN);
-
-	sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-	if (sk < 0) {
-		perror("Can't create socket");
-		return -1;
-	}
-
-	port = atoi(argv[1]);
-	memset(&addr, 0, sizeof(addr));
-	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = htonl(INADDR_ANY);
-	addr.sin_port = htons(port);
-
-	printf("Binding to port %d\n", port);
-
-	ret = bind(sk, (struct sockaddr *)&addr, sizeof(addr));
-	if (ret < 0) {
-		perror("Can't bind socket");
-		return -1;
-	}
-
-	ret = listen(sk, 16);
-	if (ret < 0) {
-		perror("Can't put sock to listen");
-		return -1;
-	}
-
-	printf("Waiting for connections\n");
-	while (1) {
-		int ask, pid;
-
-		ask = accept(sk, NULL, NULL);
-		if (ask < 0) {
-			perror("Can't accept new conn");
-			return -1;
-		}
-
-		pid = fork();
-		if (pid < 0) {
-			perror("Can't fork");
-			return -1;
-		}
-
-		if (pid > 0)
-			close(ask);
-		else {
-			close(sk);
-			ret = serve_new_conn(ask);
-			exit(ret);
-		}
-	}
-}
diff --git a/test/unix-callback/Makefile b/test/unix-callback/Makefile
deleted file mode 100644
index f2993c5..0000000
--- a/test/unix-callback/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-all: unix-lib.so unix-server unix-client syslog-lib.so
-
-run: all
-	./run.sh
-
-unix.pb-c.c: unix.proto
-	protoc-c --proto_path=. --c_out=. unix.proto
-
-unix-lib.so: unix-lib.c unix.pb-c.c
-	gcc -g -Werror -Wall -shared -nostartfiles unix-lib.c unix.pb-c.c -o unix-lib.so -iquote ../../include -fPIC
-
-syslog-lib.so: syslog-lib.c
-	gcc -g -Werror -Wall -shared -nostartfiles syslog-lib.c -o syslog-lib.so -iquote ../../include -fPIC
-
-unix-server: unix-server.c
-	gcc -Werror -Wall -o unix-server unix-server.c
-
-unix-client: unix-client.c
-	gcc -Werror -Wall -o unix-client unix-client.c
-
-clean:
-	rm -rf data unix-lib.so unix-server unix-client syslog-lib.so output pid unix.pb-c.*
diff --git a/test/unix-callback/lib/syslog-lib.so b/test/unix-callback/lib/syslog-lib.so
deleted file mode 120000
index 6a2d849..0000000
--- a/test/unix-callback/lib/syslog-lib.so
+++ /dev/null
@@ -1 +0,0 @@
-../syslog-lib.so
\ No newline at end of file
diff --git a/test/unix-callback/lib/unix-lib.so b/test/unix-callback/lib/unix-lib.so
deleted file mode 120000
index 19c491e..0000000
--- a/test/unix-callback/lib/unix-lib.so
+++ /dev/null
@@ -1 +0,0 @@
-../unix-lib.so
\ No newline at end of file
diff --git a/test/unix-callback/run.sh b/test/unix-callback/run.sh
deleted file mode 100755
index ec5b7f5..0000000
--- a/test/unix-callback/run.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/bin/bash -x
-
-cd `dirname $0`
-
-source ../env.sh || exit 1
-
-rm -rf /tmp/criu.unix.callback.test*
-test -f pid && unlink pid
-test -f output && unlink output
-rm -rf data
-mkdir -p data
-
-./unix-server &
-srv_pid=$!
-
-for i in `seq 20`; do
-	test -f /tmp/criu.unix.callback.test && break
-	sleep 0.1
-done
-
-( setsid ./unix-client < /dev/null &> output ) &
-
-while :; do
-	test -f pid && break
-	sleep 1
-done
-
-pid=`cat pid`
-
-${CRIU} dump -D data -o dump.log -v4 --lib `pwd`/lib -t $pid || exit 1
-kill $srv_pid
-wait $srv_pid
-unlink /tmp/criu.unix.callback.test
-./unix-server &
-srv_pid=$!
-for i in `seq 20`; do
-	test -f /tmp/criu.unix.callback.test && break
-	sleep 0.1
-done
-${CRIU} restore -D data -o restore.log -v4 --lib `pwd`/lib -d || exit 1
-kill $pid
-while :; do
-	cat output | grep PASS && break
-	sleep 1
-done
-
-cat output
-kill $srv_pid
diff --git a/test/unix-callback/syslog-lib.c b/test/unix-callback/syslog-lib.c
deleted file mode 100644
index c7950ca..0000000
--- a/test/unix-callback/syslog-lib.c
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include "criu-plugin.h"
-#include "criu-log.h"
-
-extern cr_plugin_dump_unix_sk_t cr_plugin_dump_unix_sk;
-extern cr_plugin_restore_unix_sk_t cr_plugin_restore_unix_sk;
-
-int cr_plugin_dump_unix_sk(int sk, int id)
-{
-	struct sockaddr_un addr;
-	socklen_t addr_len = sizeof(addr);
-	char buf[4096];
-	int fd;
-
-	if (getsockname(sk, (struct sockaddr *) &addr, &addr_len) < 0)
-		return -1;
-
-	if (strncmp(addr.sun_path, "/dev/log", addr_len - sizeof(addr.sun_family)))
-		return -ENOTSUP;
-
-	snprintf(buf, sizeof(buf), "syslog-%x.img", id);
-	fd = open(buf, O_WRONLY | O_CREAT);
-	if (fd < 0)
-		return -1;
-	close(fd);
-
-	return 0;
-}
-
-int cr_plugin_restore_unix_sk(int id)
-{
-	struct sockaddr_un addr;
-	socklen_t addr_len;
-	char buf[4096];
-	int sk, fd;
-
-	snprintf(buf, sizeof(buf), "syslog-%x.img", id);
-	fd = open(buf, O_RDONLY);
-	if (fd < 0)
-		return -ENOTSUP;
-	close(fd);
-
-	sk = socket(AF_FILE, SOCK_DGRAM|SOCK_CLOEXEC, 0);
-	if (sk == -1)
-		return sk;
-
-	addr.sun_family = AF_FILE;
-	addr_len = strlen("/dev/log");
-	strncpy(addr.sun_path, "/dev/log", addr_len);
-	addr_len += sizeof(addr.sun_family);
-	if (connect(sk, (struct sockaddr *) &addr, addr_len) == -1) {
-		close(sk);
-		return -1;
-	}
-
-	return sk;
-}
diff --git a/test/unix-callback/unix-client.c b/test/unix-callback/unix-client.c
deleted file mode 100644
index 69808b5..0000000
--- a/test/unix-callback/unix-client.c
+++ /dev/null
@@ -1,121 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <signal.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <linux/un.h>
-#include <fcntl.h>
-
-#include <syslog.h>
-
-#define SK_NAME "/tmp/criu.unix.callback.test"
-
-#define SK_NR 2
-struct {
-	int id;
-	int sk;
-	int val;
-} sks[SK_NR];
-
-static int create_sock(int i)
-{
-	int ret, id, sk, val = time(NULL) + i * 314;
-	char buf[4096];
-	struct sockaddr_un addr;
-	socklen_t addr_len;
-
-	id = getpid() * 10 + i;
-	sk = socket(AF_UNIX, SOCK_DGRAM, 0);
-	if (sk < 0)
-		return -1;
-
-	addr.sun_family = AF_UNIX;
-	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s%d", SK_NAME, id);
-	addr_len += sizeof(addr.sun_family);
-
-	if (bind(sk, (struct sockaddr *) &addr, addr_len) < 0) {
-		perror("bind");
-		return 1;
-	}
-
-	addr.sun_family = AF_UNIX;
-	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, SK_NAME);
-	addr_len += sizeof(addr.sun_family);
-
-	if (connect(sk, (struct sockaddr *) &addr, addr_len) < 0) {
-		perror("connect");
-		return 1;
-	}
-
-	printf("init %d\n", val);
-	ret = sprintf(buf, "t%d", val);
-	if (send(sk, buf, ret, 0) < 0) {
-		perror("send");
-		return -1;
-	}
-
-	sks[i].sk = sk;
-	sks[i].val = val;
-
-	return 0;
-}
-
-static int check_sock(int i)
-{
-	int sk = sks[i].sk, val = sks[i].val;
-	char buf[4096];
-
-	if (send(sk, "r", 1, 0) < 0) {
-		perror("send(\"r\")");
-		return -1;
-	}
-
-	if (recv(sk, buf, sizeof(buf), 0) <= 0) {
-		perror("recv");
-		return -1;
-	}
-
-	printf("%s - %d\n", buf, val);
-	if (atoi(buf) != val)
-		return -1;
-
-	return 0;
-}
-
-int main()
-{
-	int i, fd;
-	sigset_t set;
-	int sig;
-
-	for (i = 0; i < SK_NR; i++)
-		if (create_sock(i))
-			return -1;
-
-	fd = open("pid", O_WRONLY | O_CREAT, 0666);
-	if (fd < 0)
-		return 1;
-	dprintf(fd, "%d\n", getpid());
-	close(fd);
-
-	openlog("test", LOG_NDELAY, LOG_USER );
-
-	sigemptyset(&set);
-	sigaddset(&set, SIGTERM);
-	sigprocmask(SIG_BLOCK, &set, NULL);
-	sigwait(&set, &sig);
-
-	syslog(LOG_CRIT, "test message");
-
-	for (i = 0; i < SK_NR; i++)
-		if (check_sock(i))
-			return -1;
-
-	printf("PASS\n");
-	return 0;
-}
-
diff --git a/test/unix-callback/unix-lib.c b/test/unix-callback/unix-lib.c
deleted file mode 100644
index 44b1498..0000000
--- a/test/unix-callback/unix-lib.c
+++ /dev/null
@@ -1,187 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <errno.h>
-
-#include <sys/socket.h>
-#include <linux/un.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "criu-plugin.h"
-#include "criu-log.h"
-
-#include "unix.pb-c.h"
-
-extern cr_plugin_init_t cr_plugin_init;
-extern cr_plugin_dump_unix_sk_t cr_plugin_dump_unix_sk;
-extern cr_plugin_restore_unix_sk_t cr_plugin_restore_unix_sk;
-
-#define SK_NAME "/tmp/criu.unix.callback.test"
-static int get_srv_socket(void)
-{
-	struct sockaddr_un addr;
-	socklen_t addr_len;
-	int skd;
-
-	skd = socket(AF_UNIX, SOCK_DGRAM, 0);
-	if (skd < 0) {
-		pr_perror("socket");
-		return -1;
-	}
-
-	addr.sun_family = AF_UNIX;
-	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, "%s.dump.%d", SK_NAME, getpid());
-	addr_len += sizeof(addr.sun_family);
-
-	unlink(addr.sun_path);
-	if (bind(skd, (struct sockaddr *) &addr, addr_len) < 0) {
-		pr_perror("bind");
-		return 1;
-	}
-
-	addr.sun_family = AF_UNIX;
-	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, SK_NAME);
-	addr_len += sizeof(addr.sun_family);
-
-	if (connect(skd, (struct sockaddr *) &addr, addr_len) < 0) {
-		pr_perror("connect");
-		return -1;
-	}
-
-	return skd;
-}
-
-int cr_plugin_init(void)
-{
-	return 0;
-}
-
-int cr_plugin_dump_unix_sk(int sk, int sk_id)
-{
-	struct sockaddr_un addr;
-	socklen_t addr_len = sizeof(addr);
-	char buf[4096];
-	int skd, id, ret, fd, len;
-	UnixTest e = UNIX_TEST__INIT;
-
-	if (getpeername(sk, (struct sockaddr *) &addr, &addr_len)) {
-		pr_perror("getpeername");
-		return -1;
-	}
-
-	len = addr_len - sizeof(addr.sun_family);
-	if (addr.sun_path[len - 1] == 0)
-		len--;
-
-	if (len != strlen(SK_NAME) ||
-	    strncmp(addr.sun_path, SK_NAME, strlen(SK_NAME)))
-		return -ENOTSUP;
-
-	pr_info("Dump the socket %x\n", sk_id);
-	skd = get_srv_socket();
-	if (skd < 0)
-		return -1;
-
-	addr_len = sizeof(struct sockaddr_un);
-
-	if (getsockname(sk, (struct sockaddr *) &addr, &addr_len) < 0)
-		return -1;
-
-	id = atoi(addr.sun_path + strlen(SK_NAME));
-
-	ret = sprintf(buf, "d%d", id) + 1;
-	if (send(skd, buf, ret, 0) < 0) {
-		pr_perror("send");
-		return -1;
-	}
-
-	if (recv(skd, buf, sizeof(buf), 0) <= 0)
-		return -1;
-
-	close(skd);
-
-	e.val = atoi(buf);
-	pr_err("%x: val %d\n", sk_id, e.val);
-	e.name.data = (void *)addr.sun_path;
-	e.name.len = addr_len - sizeof(addr.sun_family);
-
-	snprintf(buf, sizeof(buf), "unix-test-%x.img", sk_id);
-	fd = openat(criu_get_image_dir(), buf, O_WRONLY | O_CREAT, 0600);
-	if (fd < 0)
-		return -1;
-
-	if (unix_test__get_packed_size(&e) > sizeof(buf)) {
-		pr_err("%ld\n", unix_test__get_packed_size(&e));
-		return -1;
-	}
-
-	ret = unix_test__pack(&e, (uint8_t *) buf);
-	if (write(fd, buf, ret) != ret)
-		return -1;
-	close(fd);
-
-	return 0;
-}
-
-int cr_plugin_restore_unix_sk(int sk_id)
-{
-	struct sockaddr_un addr;
-	socklen_t addr_len;
-	int fd, sk, ret;
-	char buf[4096];
-	UnixTest *e;
-
-	snprintf(buf, sizeof(buf), "unix-test-%x.img", sk_id);
-	fd = openat(criu_get_image_dir(), buf, O_RDONLY, 0600);
-	if (fd < 0)
-		return -ENOTSUP;
-
-	ret = read(fd, buf, sizeof(buf));
-	if (ret < 0) {
-		pr_perror("read");
-		return -1;
-	}
-	close(fd);
-
-	e = unix_test__unpack(NULL, ret, (uint8_t *) buf);
-	if (e == NULL)
-		return -1;
-
-	sk = socket(AF_UNIX, SOCK_DGRAM, 0);
-	if (sk < 0) {
-		pr_perror("socket");
-		return -1;
-	}
-
-	addr.sun_family = AF_UNIX;
-	memcpy(addr.sun_path, e->name.data, e->name.len);
-	addr_len = sizeof(addr.sun_family) + e->name.len;
-
-	if (bind(sk, (struct sockaddr *) &addr, addr_len) < 0) {
-		pr_perror("bind");
-		return -1;
-	}
-
-	addr.sun_family = AF_UNIX;
-	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, SK_NAME);
-	addr_len += sizeof(addr.sun_family);
-
-	if (connect(sk, (struct sockaddr *) &addr, addr_len) < 0) {
-		pr_perror("connect");
-		return -1;
-	}
-
-	pr_err("id %d val %d\n", sk_id, e->val);
-	ret = sprintf(buf, "t%d", e->val);
-	if (send(sk, buf, ret, 0) < 0) {
-		pr_perror("send");
-		return -1;
-	}
-
-	return sk;
-}
diff --git a/test/unix-callback/unix-server.c b/test/unix-callback/unix-server.c
deleted file mode 100644
index 8f32f53..0000000
--- a/test/unix-callback/unix-server.c
+++ /dev/null
@@ -1,104 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <linux/un.h>
-
-struct ticket
-{
-	struct ticket *next;
-	int val;
-	int id;
-};
-
-struct ticket *tickets;
-
-#define SK_NAME "/tmp/criu.unix.callback.test"
-
-int main()
-{
-	int sk, ret, id;
-	char buf[4096];
-	struct ticket *t;
-	struct sockaddr_un addr;
-	socklen_t addr_len;
-	struct stat st;
-
-	unlink(SK_NAME);
-
-	sk = socket(AF_UNIX, SOCK_DGRAM, 0);
-	if (sk < 0) {
-		perror("socket");
-		return -1;
-	}
-
-	addr.sun_family = AF_UNIX;
-	addr_len = snprintf(addr.sun_path, UNIX_PATH_MAX, SK_NAME);
-	addr_len += sizeof(addr.sun_family);
-
-	if (bind(sk, (struct sockaddr *) &addr, addr_len) < 0) {
-		perror("bind");
-		return 1;
-	}
-
-	fstat(sk, &st);
-
-	while (1) {
-		addr_len = sizeof(struct sockaddr_un);
-		ret = recvfrom(sk, buf, sizeof(buf), 0, (struct sockaddr *) &addr, &addr_len);
-		if (ret == 0)
-			return 0;
-		if (ret < 0) {
-			perror("recvfrom");
-			return 1;
-		}
-		id = 0;
-		switch (buf[0]) {
-		case 'l':
-			ret = sprintf(buf, "%ld", st.st_ino);
-			if (sendto(sk, buf, ret + 1, 0, (struct sockaddr *) &addr, addr_len) < 0) {
-				perror("sendto");
-				return -1;
-			}
-			break;
-		case 't': /* ticket */
-			t = malloc(sizeof(struct ticket));
-			if (t == 0) {
-				perror("Can't allocate memory");
-				return 1;
-			}
-
-			t->val = atoi(buf + 1);
-			t->next = tickets;
-			t->id = atoi(addr.sun_path +strlen(SK_NAME));
-			printf("t: id %d val %d\n", t->id, t->val);
-			tickets = t;
-			break;
-		case 'd': /* dump */
-			id = atoi(buf + 1);
-		case 'r': /* request */
-			if (!id)
-				id = atoi(addr.sun_path + strlen(SK_NAME));
-			for (t = tickets; t; t = t->next)
-				if (t->id == id)
-					break;
-			if (t == NULL)
-				return 1;
-			printf("r: id %d val %d\n", id, t->val);
-			ret = sprintf(buf, "%d", t->val);
-			if (sendto(sk, buf, ret + 1, 0, (struct sockaddr *) &addr, addr_len) < 0) {
-				perror("sendto");
-				return 1;
-			}
-			break;
-		default:
-			return -1;
-		}
-	}
-
-	return 0;
-}
diff --git a/test/unix-callback/unix.proto b/test/unix-callback/unix.proto
deleted file mode 100644
index fb06fc8..0000000
--- a/test/unix-callback/unix.proto
+++ /dev/null
@@ -1,4 +0,0 @@
-message unix_test {
-	required uint32 val = 1;
-	required bytes name = 2;
-}
-- 
2.5.0



More information about the CRIU mailing list