Skip to contentSkip to conversation

IPC: message queue checkpoint/restore - requested updates

PATCH Superseded Stanislav Kinsbursky 3 participants 9 messages Apr 9, 2012 – Apr 10, 2012

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover IPC: message queue checkpoint/restore - requested updates

This patch set updates IPC checkpoint/restore support according to discussion of previous patch set named "IPC: message queue checkpoint support". What has been changed:
1) MSG_STEAL was replaced by MSG_PEEK_ALL (as suggested by Michael Kerrisk)
2) All checkpoint/restore code has been put under CONFIG_CHECKPOINT_RESTORE define.
3) Added return of ENOSYS in case of sys_msgrcv was called with MSG_PEEK_ALL flag, but kernel was compiled without checkpoint/restore support.
4) Test for support of SYSV IPC message queues checkpoint/restore added to the series. Test file: msgque.c

Michael, please, tell me, what I have to do (or provide) to update man page accordingly.

The following series consists of:

---

Stanislav Kinsbursky (4):
ipc: rename obfuscating MSG_STEAL flag into MSG_PEEK_ALL
ipc: move all checkpoint-restore code under appropriate define
ipc: handle MSG_PEEK_ALL flag if CONFIG_CHECKPOINT_RESTORE is dropped
test: IPC message queue migration test

 include/linux/msg.h |    2 -
 ipc/compat.c        |   16 ++++-
 ipc/msg.c           |   27 +++++++--
 msgque.c            |  151 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 185 insertions(+), 11 deletions(-)
 create mode 100644 msgque.c
#1 lore raw

PATCH 1/4 ipc: rename obfuscating MSG_STEAL flag into MSG_PEEK_ALL

MSG_PEEK_ALL looks familiar because MSG_PEEK for one socket message is used already.

---
 include/linux/msg.h |    2 +-
 ipc/compat.c        |    6 +++---
 ipc/msg.c           |   10 +++++-----
 3 files changed, 9 insertions(+), 9 deletions(-)
include/linux/msg.h +1 -1
index 5eb43a2..bd8fe66 100644
@@ -11,7 +11,7 @@
 /* msgrcv options */
 #define MSG_NOERROR     010000  /* no error if message is too big */
 #define MSG_EXCEPT      020000  /* recv any msg except of specified type.*/
-#define MSG_STEAL       040000  /* copy (not remove) all queue messages */
+#define MSG_PEEK_ALL    040000  /* copy (not remove) all queue messages */
 
 /* Obsolete, used only for backwards compatibility and libc5 compiles */
 struct msqid_ds {
ipc/compat.c +3 -3
index d2b34f8..96cb9db 100644
@@ -335,7 +335,7 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
 }
 
 
-static long compat_do_msg_steal(void __user *dest, struct msg_msg *msg, size_t bufsz)
+static long compat_do_msg_peek_all(void __user *dest, struct msg_msg *msg, size_t bufsz)
 {
 	struct compat_msgbuf_a __user *msgp = dest;
 	size_t msgsz;
@@ -387,8 +387,8 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
 		msgtyp = ipck.msgtyp;
 	}
 	return do_msgrcv(first, uptr, second, msgtyp, third,
-			 (third & MSG_STEAL) ? compat_do_msg_steal
-					      : compat_do_msg_fill);
+			 (third & MSG_PEEK_ALL) ? compat_do_msg_peek_all
+						: compat_do_msg_fill);
 }
 
 static inline int get_compat_msqid64(struct msqid64_ds *m64,
ipc/msg.c +5 -5
index 64f83b6..017bf0b 100644
@@ -762,7 +762,7 @@ static inline int convert_mode(long *msgtyp, int msgflg)
 	return SEARCH_EQUAL;
 }
 
-static long do_msg_steal(void __user *dest, struct msg_msg *msg, size_t bufsz)
+static long do_msg_peek_all(void __user *dest, struct msg_msg *msg, size_t bufsz)
 {
 	struct msgbuf_a __user *msgp = dest;
 	size_t msgsz;
@@ -845,7 +845,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
 						walk_msg->m_type != 1) {
 					msg = walk_msg;
 					msgtyp = walk_msg->m_type - 1;
-				} else if (msgflg & MSG_STEAL) {
+				} else if (msgflg & MSG_PEEK_ALL) {
 					long ret;
 
 					ret = msg_fill(buf, msg, arrsz);
@@ -863,7 +863,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
 			tmp = tmp->next;
 		}
 		if (!IS_ERR(msg)) {
-			if (msgflg & MSG_STEAL)
+			if (msgflg & MSG_PEEK_ALL)
 				goto out_unlock;
 			/*
 			 * Found a suitable message.
@@ -959,7 +959,7 @@ out_unlock:
 	if (IS_ERR(msg))
 		return PTR_ERR(msg);
 
-	if (msgflg & MSG_STEAL)
+	if (msgflg & MSG_PEEK_ALL)
 		return bufsz - arrsz;
 
 	bufsz = msg_fill(buf, msg, bufsz);
@@ -972,7 +972,7 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
 		long, msgtyp, int, msgflg)
 {
 	return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg,
-			 (msgflg & MSG_STEAL) ? do_msg_steal : do_msg_fill);
+			 (msgflg & MSG_PEEK_ALL) ? do_msg_peek_all : do_msg_fill);
 }
 
 #ifdef CONFIG_PROC_FS
#2 lore raw

PATCH 2/4 ipc: move all checkpoint-restore code under appropriate define

In reply to Stanislav Kinsbursky

All new checkpoint/restore code parts are now covered with CONFIG_CHECKPOINT_RESTORE marco. So it would be easy to remove them, in case the whole project fails.

---
 ipc/compat.c |    9 ++++++---
 ipc/msg.c    |   15 ++++++++++++++-
 2 files changed, 20 insertions(+), 4 deletions(-)
ipc/compat.c +6 -3
index 96cb9db..bb9350d 100644
@@ -334,7 +334,7 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
 	return do_msgsnd(first, type, up->mtext, second, third);
 }
 
-
+#ifdef CONFIG_CHECKPOINT_RESTORE
 static long compat_do_msg_peek_all(void __user *dest, struct msg_msg *msg, size_t bufsz)
 {
 	struct compat_msgbuf_a __user *msgp = dest;
@@ -354,6 +354,7 @@ static long compat_do_msg_peek_all(void __user *dest, struct msg_msg *msg, size_
 		return -EFAULT;
 	return msgsz;
 }
+#endif
 
 long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
 {
@@ -387,8 +388,10 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
 		msgtyp = ipck.msgtyp;
 	}
 	return do_msgrcv(first, uptr, second, msgtyp, third,
-			 (third & MSG_PEEK_ALL) ? compat_do_msg_peek_all
-						: compat_do_msg_fill);
+#ifdef CONFIG_CHECKPOINT_RESTORE
+			 (third & MSG_PEEK_ALL) ? compat_do_msg_peek_all :
+#endif
+						compat_do_msg_fill);
 }
 
 static inline int get_compat_msqid64(struct msqid64_ds *m64,
ipc/msg.c +14 -1
index 017bf0b..8d63cc7 100644
@@ -762,6 +762,7 @@ static inline int convert_mode(long *msgtyp, int msgflg)
 	return SEARCH_EQUAL;
 }
 
+#ifdef CONFIG_CHECKPOINT_RESTORE
 static long do_msg_peek_all(void __user *dest, struct msg_msg *msg, size_t bufsz)
 {
 	struct msgbuf_a __user *msgp = dest;
@@ -788,6 +789,7 @@ static long do_msg_peek_all(void __user *dest, struct msg_msg *msg, size_t bufsz
 		return -EFAULT;
 	return msgsz;
 }
+#endif
 
 static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
 {
@@ -811,7 +813,9 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
 	struct msg_msg *msg;
 	int mode;
 	struct ipc_namespace *ns;
+#ifdef CONFIG_CHECKPOINT_RESTORE
 	size_t arrsz = bufsz;
+#endif
 
 	if (msqid < 0 || (long) bufsz < 0)
 		return -EINVAL;
@@ -845,6 +849,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
 						walk_msg->m_type != 1) {
 					msg = walk_msg;
 					msgtyp = walk_msg->m_type - 1;
+#ifdef CONFIG_CHECKPOINT_RESTORE
 				} else if (msgflg & MSG_PEEK_ALL) {
 					long ret;
 
@@ -855,6 +860,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
 					}
 					buf += ret;
 					arrsz -= ret;
+#endif
 				} else {
 					msg = walk_msg;
 					break;
@@ -863,8 +869,10 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
 			tmp = tmp->next;
 		}
 		if (!IS_ERR(msg)) {
+#ifdef CONFIG_CHECKPOINT_RESTORE
 			if (msgflg & MSG_PEEK_ALL)
 				goto out_unlock;
+#endif
 			/*
 			 * Found a suitable message.
 			 * Unlink it from the queue.
@@ -959,8 +967,10 @@ out_unlock:
 	if (IS_ERR(msg))
 		return PTR_ERR(msg);
 
+#ifdef CONFIG_CHECKPOINT_RESTORE
 	if (msgflg & MSG_PEEK_ALL)
 		return bufsz - arrsz;
+#endif
 
 	bufsz = msg_fill(buf, msg, bufsz);
 	free_msg(msg);
@@ -972,7 +982,10 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
 		long, msgtyp, int, msgflg)
 {
 	return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg,
-			 (msgflg & MSG_PEEK_ALL) ? do_msg_peek_all : do_msg_fill);
+#ifdef CONFIG_CHECKPOINT_RESTORE
+			 (msgflg & MSG_PEEK_ALL) ? do_msg_peek_all :
+#endif
+			 do_msg_fill);
 }
 
 #ifdef CONFIG_PROC_FS
#3 lore raw

Re: [CRIU] [PATCH 2/4] ipc: move all checkpoint-restore code under appropriate define

Quoted 10 lines · Stanislav Kinsbursky

All new checkpoint/restore code parts are now covered with CONFIG_CHECKPOINT_RESTORE marco. So it would be easy to remove them, in case the whole project fails.

---
 ipc/compat.c |    9 ++++++---
 ipc/msg.c    |   15 ++++++++++++++-
 2 files changed, 20 insertions(+), 4 deletions(-)

ipc/compat.c long compat_sys_msgrcv(int first, int second, int msgtyp, int third, · line 394

Quoted 9 lines
ipc/compat.c +4 -2
@@ -387,8 +388,10 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
 		msgtyp = ipck.msgtyp;
 	}
 	return do_msgrcv(first, uptr, second, msgtyp, third,
-			 (third & MSG_PEEK_ALL) ? compat_do_msg_peek_all
-						: compat_do_msg_fill);
+#ifdef CONFIG_CHECKPOINT_RESTORE
+			 (third & MSG_PEEK_ALL) ? compat_do_msg_peek_all :
+#endif
+						compat_do_msg_fill);

These ifdefs in the middle of the code look not very elegant. Is there a way to replace the checks they surround with static inline function (reporting 0 when CHECKPOINT_RESTORE is off) potentially letting the compiler optimize out the code sitting under if (0) ?

Quoted 5 lines
ipc/compat.c +0 -0
 }
 
 static inline int get_compat_msqid64(struct msqid64_ds *m64,
ipc/msg.c +0 -0
index 017bf0b..8d63cc7 100644
#4 lore raw

Re: [CRIU] [PATCH 2/4] ipc: move all checkpoint-restore code under appropriate define

09.04.2012 23:47, Pavel Emelyanov пишет:

Quoted 10 lines · Stanislav Kinsbursky
Quoted 9 lines

All new checkpoint/restore code parts are now covered with CONFIG_CHECKPOINT_RESTORE marco. So it would be easy to remove them, in case the whole project fails.

---
  ipc/compat.c |    9 ++++++---
  ipc/msg.c    |   15 ++++++++++++++-
  2 files changed, 20 insertions(+), 4 deletions(-)
Quoted 16 lines

ipc/compat.c long compat_sys_msgrcv(int first, int second, int msgtyp, int third, · line 394

Quoted 10 lines
ipc/compat.c +4 -2
@@ -387,8 +388,10 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
  		msgtyp = ipck.msgtyp;
  	}
  	return do_msgrcv(first, uptr, second, msgtyp, third,
-			 (third&  MSG_PEEK_ALL) ? compat_do_msg_peek_all
-						: compat_do_msg_fill);
+#ifdef CONFIG_CHECKPOINT_RESTORE
+			 (third&  MSG_PEEK_ALL) ? compat_do_msg_peek_all :
+#endif
+						compat_do_msg_fill);

These ifdefs in the middle of the code look not very elegant. Is there a way to replace the checks they surround with static inline function (reporting 0 when CHECKPOINT_RESTORE is off) potentially letting the compiler optimize out the code sitting under if (0) ?

Yes, sure. I'll do this.

Signature · 2 lines
Best regards,
Stanislav Kinsbursky
#5 lore raw

PATCH v2 2/4 ipc: move all checkpoint-restore code under appropriate define

In reply to Pavel Emelyanov

v2: added dummy compat_do_msg_peek_all() and do_msg_peek_all() functions used in case of CONFIG_CHECKPOINT_RESTORE is not defined.

All new checkpoint/restore code parts are now covered with CONFIG_CHECKPOINT_RESTORE macro. So it would be easy to remove them, in case the whole project fails.

---
 ipc/compat.c |    8 +++++++-
 ipc/msg.c    |   15 +++++++++++++++
 2 files changed, 22 insertions(+), 1 deletions(-)
ipc/compat.c +1 -1
index 96cb9db..87317ff 100644
@@ -334,7 +334,7 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
        return do_msgsnd(first, type, up->mtext, second, third);
 }
 
-
+#ifdef CONFIG_CHECKPOINT_RESTORE
 static long compat_do_msg_peek_all(void __user *dest, struct msg_msg *msg, 

size_t bufsz)

 {
        struct compat_msgbuf_a __user *msgp = dest;
@@ -354,6 +354,12 @@ static long compat_do_msg_peek_all(void __user *dest, struct msg_msg *msg, size_
                return -EFAULT;
        return msgsz;

}
+#else
+static long compat_do_msg_peek_all(void __user *dest, struct msg_msg *msg, size_t bufsz) +{
+ return -EINVAL;
+}
+#endif

long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) {

ipc/msg.c +15 -0
index 017bf0b..af08fe6 100644
@@ -762,6 +762,7 @@ static inline int convert_mode(long *msgtyp, int msgflg)
        return SEARCH_EQUAL;
 }
 
+#ifdef CONFIG_CHECKPOINT_RESTORE
 static long do_msg_peek_all(void __user *dest, struct msg_msg *msg, size_t bufsz)
 {
        struct msgbuf_a __user *msgp = dest;
@@ -788,6 +789,12 @@ static long do_msg_peek_all(void __user *dest, struct msg_msg *msg, size_t bufsz
                return -EFAULT;
        return msgsz;
 }
+#else
+static long do_msg_peek_all(void __user *dest, struct msg_msg *msg, size_t bufsz)
+{
+       return -EINVAL;
+}
+#endif
 
 static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
 {
@@ -811,7 +818,9 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
        struct msg_msg *msg;
        int mode;
        struct ipc_namespace *ns;
+#ifdef CONFIG_CHECKPOINT_RESTORE
        size_t arrsz = bufsz;
+#endif
 
        if (msqid < 0 || (long) bufsz < 0)
                return -EINVAL;
@@ -845,6 +854,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
                                                walk_msg->m_type != 1) {
                                        msg = walk_msg;
                                        msgtyp = walk_msg->m_type - 1;
+#ifdef CONFIG_CHECKPOINT_RESTORE
                                } else if (msgflg & MSG_PEEK_ALL) {
                                        long ret;
 
@@ -855,6 +865,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
                                        }
                                        buf += ret;
                                        arrsz -= ret;
+#endif
                                } else {
                                        msg = walk_msg;
                                        break;
@@ -863,8 +874,10 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
                        tmp = tmp->next;
                }
                if (!IS_ERR(msg)) {
+#ifdef CONFIG_CHECKPOINT_RESTORE
                        if (msgflg & MSG_PEEK_ALL)
                                goto out_unlock;
+#endif
                        /*
                         * Found a suitable message.
                         * Unlink it from the queue.
@@ -959,8 +972,10 @@ out_unlock:
        if (IS_ERR(msg))
                return PTR_ERR(msg);
 
+#ifdef CONFIG_CHECKPOINT_RESTORE
        if (msgflg & MSG_PEEK_ALL)
                return bufsz - arrsz;
+#endif
 
        bufsz = msg_fill(buf, msg, bufsz);
        free_msg(msg);
#6 lore raw

PATCH 3/4 ipc: handle MSG_PEEK_ALL flag if CONFIG_CHECKPOINT_RESTORE is dropped

In reply to Stanislav Kinsbursky

Return -ENOSYS, if user called sys_msgrcv() with MSG_PEEK_ALL flag set and checkpoint/restore code wasn't compiled.

---
 ipc/compat.c |    5 ++++-
 ipc/msg.c    |    4 ++++
 2 files changed, 8 insertions(+), 1 deletions(-)
ipc/compat.c +4 -1
index bb9350d..0163aa1 100644
@@ -377,7 +377,10 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
 		return -EINVAL;
 	if (second < 0)
 		return -EINVAL;
-
+#ifndef CONFIG_CHECKPOINT_RESTORE
+	if (third & MSG_PEEK_ALL)
+		return -ENOSYS;
+#endif
 	if (!version) {
 		struct compat_ipc_kludge ipck;
 		if (!uptr)
ipc/msg.c +4 -0
index 8d63cc7..9d8f249 100644
@@ -819,6 +819,10 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
 
 	if (msqid < 0 || (long) bufsz < 0)
 		return -EINVAL;
+#ifndef CONFIG_CHECKPOINT_RESTORE
+	if (msgflg & MSG_PEEK_ALL)
+		return -ENOSYS;
+#endif
 	mode = convert_mode(&msgtyp, msgflg);
 	ns = current->nsproxy->ipc_ns;
 
#7 lore raw

PATCH 4/4 test: IPC message queue migration test

In reply to Stanislav Kinsbursky

This test is a part of CRIU development test suit.

---
 msgque.c |  151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 151 insertions(+), 0 deletions(-)
 create mode 100644 msgque.c
msgque.c new file +151 -0
new file mode 100644
index 0000000..9647e0a
@@ -0,0 +1,151 @@
+#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/sem.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <signal.h>
+#include <errno.h>
+
+#include "zdtmtst.h"
+
+const char *test_doc="Tests sysv5 msg queues supporting by checkpointing";
+const char *test_author="Stanislav Kinsbursky <[email protected]>";
+
+struct msg1 {
+	long mtype;
+	char mtext[20];
+};
+#define TEST_STRING "Test sysv5 msg"
+#define MSG_TYPE 1
+
+#define ANOTHER_TEST_STRING "Yet another test sysv5 msg"
+#define ANOTHER_MSG_TYPE 26538
+
+static int test_fn(int argc, char **argv)
+{
+	key_t key;
+	int msg, pid;
+	struct msg1 msgbuf;
+	int chret;
+
+	key = ftok(argv[0], 822155650);
+	if (key == -1) {
+		err("Can't make key");
+		exit(1);
+	}
+
+	pid = test_fork();
+	if (pid < 0) {
+		err("Can't fork");
+		exit(1);
+	}
+
+	msg = msgget(key, IPC_CREAT | IPC_EXCL | 0666);
+	if (msg == -1) {
+		msg = msgget(key, 0666);
+		if (msg == -1) {
+			err("Can't get queue");
+			goto err_kill;
+		}
+	}
+
+	if (pid == 0) {
+		/*
+		 * Here is the place where test sleeps and waits for signal.
+		 * This place is used for suspend/restore test.
+		 */
+		test_waitsig();
+
+		if (msgrcv(msg, &msgbuf, sizeof(TEST_STRING), MSG_TYPE, IPC_NOWAIT) == -1) {
+			fail("Child: msgrcv failed (%m)");
+			return -errno;
+		}
+
+		if (strncmp(TEST_STRING, msgbuf.mtext, sizeof(TEST_STRING))) {
+			fail("Child: the source and received strings aren't equal");
+			return -errno;
+		}
+		test_msg("Child: received %s\n", msgbuf.mtext);
+
+		msgbuf.mtype = ANOTHER_MSG_TYPE;
+		memcpy(msgbuf.mtext, ANOTHER_TEST_STRING, sizeof(ANOTHER_TEST_STRING));
+		if (msgsnd(msg, &msgbuf, sizeof(ANOTHER_TEST_STRING), IPC_NOWAIT) != 0) {
+			fail("Child: msgsnd failed (%m)");
+			return -errno;
+		};
+		pass();
+		return 0;
+	} else {
+		msgbuf.mtype = MSG_TYPE;
+		memcpy(msgbuf.mtext, TEST_STRING, sizeof(TEST_STRING));
+		if (msgsnd(msg, &msgbuf, sizeof(TEST_STRING), IPC_NOWAIT) != 0) {
+			fail("Parent: msgsnd failed (%m)");
+			goto err_kill;
+		};
+
+		msgbuf.mtype = ANOTHER_MSG_TYPE;
+		memcpy(msgbuf.mtext, ANOTHER_TEST_STRING, sizeof(ANOTHER_TEST_STRING));
+		if (msgsnd(msg, &msgbuf, sizeof(ANOTHER_TEST_STRING), IPC_NOWAIT) != 0) {
+			fail("child: msgsnd (2) failed (%m)");
+			return -errno;
+		};
+
+		test_daemon();
+		test_waitsig();
+
+		kill(pid, SIGTERM);
+
+		wait(&chret);
+		chret = WEXITSTATUS(chret);
+		if (chret) {
+			fail("Parent: child exited with non-zero code %d (%s)\n",
+			     chret, strerror(chret));
+			goto out;
+		}
+
+		if (msgrcv(msg, &msgbuf, sizeof(ANOTHER_TEST_STRING), ANOTHER_MSG_TYPE, IPC_NOWAIT) == -1) {
+			fail("Parent: msgrcv failed (%m)");
+			goto err;
+		}
+
+		if (strncmp(ANOTHER_TEST_STRING, msgbuf.mtext, sizeof(ANOTHER_TEST_STRING))) {
+			fail("Parent: the source and received strings aren't equal");
+			goto err;
+		}
+		test_msg("Parent: received %s\n", msgbuf.mtext);
+
+		pass();
+	}
+
+out:
+	if (msgctl(msg, IPC_RMID, 0)) {
+		fail("Failed to destroy message queue: %d\n", -errno);
+		return -errno;
+	}
+	return chret;
+
+err_kill:
+	kill(pid, SIGKILL);
+	wait(NULL);
+err:
+	chret = -errno;
+	goto out;
+}
+
+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();
+#endif
+	return 0;
+}
#8 lore raw

Re: [PATCH 4/4] test: IPC message queue migration test

Quoted 4 lines · On Mon, 09 Apr 2012 21:54:19 +0400 Stanislav Kinsbursky…

This test is a part of CRIU development test suit.

---
 msgque.c |  151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Neat. Can you please integrate this into tools/testing/selftests? You'll need to decide whether it should be under tools/testing/selftests/checkpoint-restore or tools/testing/selftests/ipc. Perhaps the former, as you guys will hopefully have more userspace test harnesses?

Also, I suggest that I throw away the current c-r-ipc-message-queue-stealing-feature-introduced.patch. Please fold all the changes you've made to that patch into a single patch and resend the whole series. I guess that will be two patches:
c-r-ipc-message-queue-stealing-feature-introduced-v2 and the tools/testing/selftests/ addition.