[CRIU] [PATCH] zdtm: IPC semaphores migration test

Kinsbursky Stanislav skinsbursky at openvz.org
Thu Feb 9 09:46:36 EST 2012


2 processes - 1 semaphore per each. Both processes checks it's sem migration
by id. Child also checks parent semaphore migration my key.

Signed-off-by: Stanislav Kinsbursky <skinsbursky at parallels.com>

---
 test/zdtm/live/static/Makefile |    2 
 test/zdtm/live/static/sem.c    |  223 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 225 insertions(+), 0 deletions(-)
 create mode 100644 test/zdtm/live/static/sem.c

diff --git a/test/zdtm/live/static/Makefile b/test/zdtm/live/static/Makefile
index 97d3ae4..f44e346 100644
--- a/test/zdtm/live/static/Makefile
+++ b/test/zdtm/live/static/Makefile
@@ -33,6 +33,7 @@ TST_NOFILE	=				\
 		sockets00			\
 		ipc_namespace			\
 		selfexe00			\
+		sem				\
 #		jobctl00			\
 
 TST_FILE	=				\
@@ -148,6 +149,7 @@ inotify_system_nodel:	override CFLAGS += -DNODEL
 pthread00:		override LDLIBS += -pthread
 shm:			override CFLAGS += -DNEW_IPC_NS
 msgque:			override CFLAGS += -DNEW_IPC_NS
+sem:			override CFLAGS += -DNEW_IPC_NS
 
 $(LIB):	force
 	$(MAKE) -C $(LIBDIR)
diff --git a/test/zdtm/live/static/sem.c b/test/zdtm/live/static/sem.c
new file mode 100644
index 0000000..97a73ef
--- /dev/null
+++ b/test/zdtm/live/static/sem.c
@@ -0,0 +1,223 @@
+#define _GNU_SOURCE
+#include <sched.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "zdtmtst.h"
+
+const char *test_doc="Tests IPC semaphores migrates fine";
+const char *test_author="Stanislav Kinsbursky <skinsbursky at parallels.com>";
+
+#define INIT_SEM_VAL(key)	(1 + (key & 0x3))
+
+static int sem_test(int id,
+		    struct sembuf *lock, struct sembuf *unlock,
+		    int lock_ops, int unlock_ops)
+{
+	if (semop(id, lock, lock_ops) == -1) {
+		fail("Failed to lock semaphore");
+		return -errno;
+	}
+	if (semop(id, unlock, unlock_ops) == -1) {
+		fail("Failed to unlock semaphore");
+		return -errno;
+	}
+	return 0;
+}
+
+static int check_sem_by_key(int key)
+{
+	int id;
+	struct sembuf lock[2] = {
+		{
+		.sem_num = 0,
+		.sem_op = 0,
+		.sem_flg = 0,
+		},
+		{
+		.sem_num = 0,
+		.sem_op = 1,
+		.sem_flg = 0,
+		},
+	};
+	struct sembuf unlock[1] = {
+		{
+		.sem_num = 0,
+		.sem_op = -1,
+		.sem_flg = 0,
+		}
+	};
+	int val;
+
+	id = semget(key, 1, 0777);
+	if (id  == -1) {
+		fail("Can't get sem");
+		return -errno;
+	}
+
+	val = semctl(id, 0, GETVAL);
+	if (val < 0) {
+		fail("Failed to get sem value");
+		return -errno;
+	}
+
+	return sem_test(id, lock, unlock,
+			sizeof(lock)/sizeof(struct sembuf),
+			sizeof(unlock)/sizeof(struct sembuf));
+}
+
+static int check_sem_by_id(int id, int val)
+{
+	int curr;
+	struct sembuf lock[] = {
+		{
+		.sem_num = 0,
+		.sem_op = val,
+		.sem_flg = 0,
+		},
+	};
+	struct sembuf unlock[] = {
+		{
+		.sem_num = 0,
+		.sem_op = - val * 2,
+		.sem_flg = 0,
+		}
+	};
+
+	curr = semctl(id, 0, GETVAL);
+	if (curr < 0) {
+		fail("Failed to get sem value");
+		return -errno;
+	}
+	if (curr != val) {
+		fail("Sem has wrong value: %d instead of %d\n", curr, val);
+		return -EFAULT;
+	}
+	return sem_test(id, lock, unlock,
+			sizeof(lock)/sizeof(struct sembuf),
+			sizeof(unlock)/sizeof(struct sembuf));
+}
+
+static int prepare_sem(int key, int val)
+{
+	int id;
+
+	id = semget(key, 1, 0777 | IPC_CREAT | IPC_EXCL);
+	if (id  == -1) {
+		err("Can't get sem");
+		return -errno;
+	}
+	if (semctl(id, 0, SETVAL, val) == -1) {
+		err("Can't init sem");
+		if (semctl(id, 1, IPC_RMID) == -1)
+			err("Destroy sem failed");
+		return -errno;
+	}
+	return id;
+}
+
+static int test_fn(int argc, char **argv)
+{
+	int id, key, val;
+	int pid;
+	int ret, fail_count = 0;
+	int key_parent, key_child;
+
+	test_daemon();
+
+	key_parent = ftok(argv[0], 89063453);
+	if (key_parent == -1) {
+		err("Can't make parent key");
+		return -1;
+	}
+	key_child  = ftok(argv[0], 12367524);
+	if (key_child == -1) {
+		err("Can't make child key");
+		return -1;
+	}
+
+	pid = test_fork();
+	if (pid == -1) {
+		err("Failed to fork");
+		return -1;
+	}
+	key = pid ? key_parent : key_child;
+	val = INIT_SEM_VAL(key);
+
+	id = prepare_sem(key, val);
+	if (id < 0) {
+		err("Prepare sem error");
+		fail_count++;
+		goto err_kill;
+	}
+
+	test_waitsig();
+
+	ret = check_sem_by_id(id, val);
+	if (ret < 0) {
+		fail_count++;
+		fail("Check sem by id failed");
+	}
+err_kill:
+	if (pid) {
+		kill(pid, SIGTERM);
+		waitpid(pid, &ret, 0);
+		if (!WIFEXITED(ret) || WEXITSTATUS(ret)) {
+			fail_count++;
+			err("Child failed");
+		}
+	}
+
+	if (fail_count)
+		goto out;
+
+	if (pid == 0) {
+		if (check_sem_by_key(pid ? key_child : key_parent) < 0) {
+			fail("Check sem by key failed");
+			fail_count++;
+			goto out_destroy;
+		}
+	}
+
+	val = semctl(id, 0, GETVAL);
+	if (val < 0) {
+		fail("Failed to get sem value");
+		fail_count++;
+		goto out_destroy;
+	}
+	if (val != 0) {
+		fail("Non-zero sem value: %d", val);
+		fail_count++;
+	}
+
+out_destroy:
+	ret = semctl(id, 1, IPC_RMID);
+	if (ret < 0) {
+		fail("Destroy sem failed");
+		fail_count++;
+	}
+out:
+	if (fail_count == 0)
+		pass();
+	return fail_count;
+}
+
+int main(int argc, char **argv)
+{
+#ifdef NEW_IPC_NS
+	test_init_ns(argc, argv, CLONE_NEWIPC, test_fn);
+#else
+	test_init(argc, argv);
+	test_fn(argc, argv);
+#endif
+	return 0;
+}



More information about the CRIU mailing list