[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