diff mbox series

[v1] Rewrite msgstress testing suite

Message ID 20240216122904.11446-1-andrea.cervesato@suse.de
State Superseded
Headers show
Series [v1] Rewrite msgstress testing suite | expand

Commit Message

Andrea Cervesato Feb. 16, 2024, 12:29 p.m. UTC
From: Andrea Cervesato <andrea.cervesato@suse.com>

msgstress testing suite has been rewritten, taking in consideration
that old code was not working most of the times. The new algorithm
simply generates new SysV IPC messages, spawning a sender and a
receiver which will validate data.

With the new algorithm we also reduce the amount of children which
we spawn, since we only have 2: sender and receiver. This permits to
increase the number of messages to send and to do not be depedent from
system overload.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 runtest/syscalls                              |   6 +-
 runtest/syscalls-ipc                          |   6 +-
 .../kernel/syscalls/ipc/msgstress/.gitignore  |   3 -
 .../kernel/syscalls/ipc/msgstress/Makefile    |   5 -
 .../syscalls/ipc/msgstress/msgstress01.c      | 414 +++++++---------
 .../syscalls/ipc/msgstress/msgstress02.c      | 408 ----------------
 .../syscalls/ipc/msgstress/msgstress03.c      | 299 ------------
 .../syscalls/ipc/msgstress/msgstress04.c      | 444 ------------------
 8 files changed, 171 insertions(+), 1414 deletions(-)
 delete mode 100644 testcases/kernel/syscalls/ipc/msgstress/msgstress02.c
 delete mode 100644 testcases/kernel/syscalls/ipc/msgstress/msgstress03.c
 delete mode 100644 testcases/kernel/syscalls/ipc/msgstress/msgstress04.c

Comments

Cyril Hrubis March 7, 2024, 11:33 a.m. UTC | #1
Hi!
First of all this patch removes all users of the libltpipc library but
keeps the library orphaned in libs/ leaving a dead code.

Secondly if you look at the libmsgctl.c you can actually see that the
reader and writer pair sends messages in a loop. This is imporatant
because without that the test can be hardly called a stress test. The
point is to start as much processes as possible that keep sending
messages around so that eventually we saturate the system. The new test
just sends a single message, which means that the children finish too
quickly and we never run more than a single digit of read/write pairs.
Given that we now have a runtime support in the test library we should
change this so that the reader/write paris continue to send messages
around until we are out of runtime. And the runtime should be at least a
minute.

> +static void reader(const int id)
> +{
> +	int size;
> +	struct sysv_msg msg_recv;
> +	struct sysv_data *buff = NULL;
>  
> -	/* Fork a number of processes, each of which will
> -	 * create a message queue with one reader/writer
> -	 * pair which will read and write a number (iterations)
> -	 * of random length messages with specific values.
> -	 */
> +	memset(&msg_recv, 0, sizeof(struct sysv_msg));
>  
> -	for (i = 0; i < nprocs; i++) {
> -		fflush(stdout);
> -		if ((pid = FORK_OR_VFORK()) < 0) {
> -			tst_brkm(TFAIL,
> -				 NULL,
> -				 "\tFork failed (may be OK if under stress)");
> -		}
> -		/* Child does this */
> -		if (pid == 0) {
> -			procstat = 1;
> -			exit(dotest(keyarray[i], i));
> +	size = SAFE_MSGRCV(id, &msg_recv, 100, MSGTYPE, 0);
> +
> +	for (int i = 0; i < ipc_data_len; i++) {
> +		if (ipc_data[i].id == id) {
> +			buff = ipc_data + i;
> +			break;
>  		}
> -		pidarray[i] = pid;
>  	}
>  
> -	count = 0;
> -	while (1) {
> -		if ((wait(&status)) > 0) {
> -			if (status >> 8 != 0) {
> -				tst_brkm(TFAIL, NULL,
> -					 "Child exit status = %d",
> -					 status >> 8);
> -			}
> -			count++;
> -		} else {
> -			if (errno != EINTR) {
> -				break;
> -			}
> -#ifdef DEBUG
> -			tst_resm(TINFO, "Signal detected during wait");
> -#endif
> -		}
> +	if (!buff) {
> +		tst_brk(TBROK, "Can't find original message. This is a test issue!");
> +		return;
>  	}
> -	/* Make sure proper number of children exited */
> -	if (count != nprocs) {
> -		tst_brkm(TFAIL,
> -			 NULL,
> -			 "Wrong number of children exited, Saw %d, Expected %d",
> -			 count, nprocs);
> +
> +	TST_EXP_EQ_LI(msg_recv.type, buff->msg.type);
> +	TST_EXP_EQ_LI(msg_recv.data.len, buff->msg.data.len);
> +
> +	for (int i = 0; i < size; i++) {
> +		if (msg_recv.data.pbytes[i] != buff->msg.data.pbytes[i]) {
> +			tst_res(TFAIL, "Received wrong data at index %d: %x != %x", i,
> +				msg_recv.data.pbytes[i],
> +				buff->msg.data.pbytes[i]);
> +
> +			goto exit;
> +		}
>  	}
>  
> -	tst_resm(TPASS, "Test ran successfully!");
> +	tst_res(TPASS, "Received correct data");

This spams the test output with a few hundreds of lines of output, which
is known to choke test runners. For this case we should probably output
one single TPASS at the end of the test.

Also this seems to be a common pattern, so we may as well add a function
into the test library that would produce TPASS unless we have seen a
FAIL/BROK/WARN. Or maybe just a function that would return sum of the
result counters so that we can do:

	if (tst_get_res(TFAIL|TBROK|TWARN))
		tst_res(TPASS, "All data were received correctly");
Andrea Cervesato March 7, 2024, 2:46 p.m. UTC | #2
Hi!

On 3/7/24 12:33, Cyril Hrubis wrote:
> Hi!
> First of all this patch removes all users of the libltpipc library but
> keeps the library orphaned in libs/ leaving a dead code.
This was done by purpose. I have track of dependences inside LTP and the 
idea is to remove it on a second moment. But I can send a following 
patch removing it already.
> Secondly if you look at the libmsgctl.c you can actually see that the
> reader and writer pair sends messages in a loop. This is imporatant
> because without that the test can be hardly called a stress test. The
> point is to start as much processes as possible that keep sending
> messages around so that eventually we saturate the system. The new test
> just sends a single message, which means that the children finish too
> quickly and we never run more than a single digit of read/write pairs.
> Given that we now have a runtime support in the test library we should
> change this so that the reader/write paris continue to send messages
> around until we are out of runtime. And the runtime should be at least a
> minute.

Actually this is a good idea, but test might send not enough messages if 
system is not responsive.
I would keep the loop like we do now in this case, so we ensure a 
certain amount of stress, no matter the runtime.

>
>> +static void reader(const int id)
>> +{
>> +	int size;
>> +	struct sysv_msg msg_recv;
>> +	struct sysv_data *buff = NULL;
>>   
>> -	/* Fork a number of processes, each of which will
>> -	 * create a message queue with one reader/writer
>> -	 * pair which will read and write a number (iterations)
>> -	 * of random length messages with specific values.
>> -	 */
>> +	memset(&msg_recv, 0, sizeof(struct sysv_msg));
>>   
>> -	for (i = 0; i < nprocs; i++) {
>> -		fflush(stdout);
>> -		if ((pid = FORK_OR_VFORK()) < 0) {
>> -			tst_brkm(TFAIL,
>> -				 NULL,
>> -				 "\tFork failed (may be OK if under stress)");
>> -		}
>> -		/* Child does this */
>> -		if (pid == 0) {
>> -			procstat = 1;
>> -			exit(dotest(keyarray[i], i));
>> +	size = SAFE_MSGRCV(id, &msg_recv, 100, MSGTYPE, 0);
>> +
>> +	for (int i = 0; i < ipc_data_len; i++) {
>> +		if (ipc_data[i].id == id) {
>> +			buff = ipc_data + i;
>> +			break;
>>   		}
>> -		pidarray[i] = pid;
>>   	}
>>   
>> -	count = 0;
>> -	while (1) {
>> -		if ((wait(&status)) > 0) {
>> -			if (status >> 8 != 0) {
>> -				tst_brkm(TFAIL, NULL,
>> -					 "Child exit status = %d",
>> -					 status >> 8);
>> -			}
>> -			count++;
>> -		} else {
>> -			if (errno != EINTR) {
>> -				break;
>> -			}
>> -#ifdef DEBUG
>> -			tst_resm(TINFO, "Signal detected during wait");
>> -#endif
>> -		}
>> +	if (!buff) {
>> +		tst_brk(TBROK, "Can't find original message. This is a test issue!");
>> +		return;
>>   	}
>> -	/* Make sure proper number of children exited */
>> -	if (count != nprocs) {
>> -		tst_brkm(TFAIL,
>> -			 NULL,
>> -			 "Wrong number of children exited, Saw %d, Expected %d",
>> -			 count, nprocs);
>> +
>> +	TST_EXP_EQ_LI(msg_recv.type, buff->msg.type);
>> +	TST_EXP_EQ_LI(msg_recv.data.len, buff->msg.data.len);
>> +
>> +	for (int i = 0; i < size; i++) {
>> +		if (msg_recv.data.pbytes[i] != buff->msg.data.pbytes[i]) {
>> +			tst_res(TFAIL, "Received wrong data at index %d: %x != %x", i,
>> +				msg_recv.data.pbytes[i],
>> +				buff->msg.data.pbytes[i]);
>> +
>> +			goto exit;
>> +		}
>>   	}
>>   
>> -	tst_resm(TPASS, "Test ran successfully!");
>> +	tst_res(TPASS, "Received correct data");
> This spams the test output with a few hundreds of lines of output, which
> is known to choke test runners. For this case we should probably output
> one single TPASS at the end of the test.
>
> Also this seems to be a common pattern, so we may as well add a function
> into the test library that would produce TPASS unless we have seen a
> FAIL/BROK/WARN. Or maybe just a function that would return sum of the
> result counters so that we can do:
>
> 	if (tst_get_res(TFAIL|TBROK|TWARN))
> 		tst_res(TPASS, "All data were received correctly");
>
>
Isn't it like this already?

Regards,
Andrea
Petr Vorel March 7, 2024, 10:07 p.m. UTC | #3
> Hi!

> On 3/7/24 12:33, Cyril Hrubis wrote:
> > Hi!
> > First of all this patch removes all users of the libltpipc library but
> > keeps the library orphaned in libs/ leaving a dead code.
> This was done by purpose. I have track of dependences inside LTP and the
> idea is to remove it on a second moment. But I can send a following patch
> removing it already.

Actually, if it was done on purpose it is a bad approach. Splitting a cleanup
from a rewrite is asking to leave a dead code.

> > Secondly if you look at the libmsgctl.c you can actually see that the
> > reader and writer pair sends messages in a loop. This is imporatant
> > because without that the test can be hardly called a stress test. The
> > point is to start as much processes as possible that keep sending
> > messages around so that eventually we saturate the system. The new test
> > just sends a single message, which means that the children finish too
> > quickly and we never run more than a single digit of read/write pairs.
> > Given that we now have a runtime support in the test library we should
> > change this so that the reader/write paris continue to send messages
> > around until we are out of runtime. And the runtime should be at least a
> > minute.

> Actually this is a good idea, but test might send not enough messages if
> system is not responsive.
> I would keep the loop like we do now in this case, so we ensure a certain
> amount of stress, no matter the runtime.

I would agree with Cyril this is not much stressing (rewrite should not drop the
main purpose of the test).


...
> > > -	tst_resm(TPASS, "Test ran successfully!");
> > > +	tst_res(TPASS, "Received correct data");
> > This spams the test output with a few hundreds of lines of output, which
> > is known to choke test runners. For this case we should probably output
> > one single TPASS at the end of the test.

Can't we exit child non-zero on failure, store that via WIFEXITED() and print
TPASS only when none of the child runs failed?

> > Also this seems to be a common pattern, so we may as well add a function
> > into the test library that would produce TPASS unless we have seen a
> > FAIL/BROK/WARN. Or maybe just a function that would return sum of the
> > result counters so that we can do:

> > 	if (tst_get_res(TFAIL|TBROK|TWARN))
> > 		tst_res(TPASS, "All data were received correctly");

This looks to me better approach than expect that the default is to TPASS.

> Isn't it like this already?

No, it TBROK if you don't produce any of TPASS/TFAIL/TBROK/TCONF (TBROK can be
only in tst_brk()):

tst_test.c:1472: TBROK: Test 0 haven't reported results!

Kind regards,
Petr

> Regards,
> Andrea
Cyril Hrubis March 8, 2024, 10:13 a.m. UTC | #4
Hi!
> > First of all this patch removes all users of the libltpipc library but
> > keeps the library orphaned in libs/ leaving a dead code.
> This was done by purpose. I have track of dependences inside LTP and the 
> idea is to remove it on a second moment. But I can send a following 
> patch removing it already.

Just add a patch that removes it as a second patch after the test
conversion.

> > Secondly if you look at the libmsgctl.c you can actually see that the
> > reader and writer pair sends messages in a loop. This is imporatant
> > because without that the test can be hardly called a stress test. The
> > point is to start as much processes as possible that keep sending
> > messages around so that eventually we saturate the system. The new test
> > just sends a single message, which means that the children finish too
> > quickly and we never run more than a single digit of read/write pairs.
> > Given that we now have a runtime support in the test library we should
> > change this so that the reader/write paris continue to send messages
> > around until we are out of runtime. And the runtime should be at least a
> > minute.
> 
> Actually this is a good idea, but test might send not enough messages if 
> system is not responsive.
> I would keep the loop like we do now in this case, so we ensure a 
> certain amount of stress, no matter the runtime.

As long as the test runs for long enough the pairs should send more or
less equal amount of messages, the scheduller should choose the
processes so that they do equal amount of work on average.

So I wouldn't be concerned with a minimal amount of loops for a given
pair, unless we want to make this into a scheduller test.

> >> +static void reader(const int id)
> >> +{
> >> +	int size;
> >> +	struct sysv_msg msg_recv;
> >> +	struct sysv_data *buff = NULL;
> >>   
> >> -	/* Fork a number of processes, each of which will
> >> -	 * create a message queue with one reader/writer
> >> -	 * pair which will read and write a number (iterations)
> >> -	 * of random length messages with specific values.
> >> -	 */
> >> +	memset(&msg_recv, 0, sizeof(struct sysv_msg));
> >>   
> >> -	for (i = 0; i < nprocs; i++) {
> >> -		fflush(stdout);
> >> -		if ((pid = FORK_OR_VFORK()) < 0) {
> >> -			tst_brkm(TFAIL,
> >> -				 NULL,
> >> -				 "\tFork failed (may be OK if under stress)");
> >> -		}
> >> -		/* Child does this */
> >> -		if (pid == 0) {
> >> -			procstat = 1;
> >> -			exit(dotest(keyarray[i], i));
> >> +	size = SAFE_MSGRCV(id, &msg_recv, 100, MSGTYPE, 0);
> >> +
> >> +	for (int i = 0; i < ipc_data_len; i++) {
> >> +		if (ipc_data[i].id == id) {
> >> +			buff = ipc_data + i;
> >> +			break;
> >>   		}
> >> -		pidarray[i] = pid;
> >>   	}
> >>   
> >> -	count = 0;
> >> -	while (1) {
> >> -		if ((wait(&status)) > 0) {
> >> -			if (status >> 8 != 0) {
> >> -				tst_brkm(TFAIL, NULL,
> >> -					 "Child exit status = %d",
> >> -					 status >> 8);
> >> -			}
> >> -			count++;
> >> -		} else {
> >> -			if (errno != EINTR) {
> >> -				break;
> >> -			}
> >> -#ifdef DEBUG
> >> -			tst_resm(TINFO, "Signal detected during wait");
> >> -#endif
> >> -		}
> >> +	if (!buff) {
> >> +		tst_brk(TBROK, "Can't find original message. This is a test issue!");
> >> +		return;
> >>   	}
> >> -	/* Make sure proper number of children exited */
> >> -	if (count != nprocs) {
> >> -		tst_brkm(TFAIL,
> >> -			 NULL,
> >> -			 "Wrong number of children exited, Saw %d, Expected %d",
> >> -			 count, nprocs);
> >> +
> >> +	TST_EXP_EQ_LI(msg_recv.type, buff->msg.type);
> >> +	TST_EXP_EQ_LI(msg_recv.data.len, buff->msg.data.len);
> >> +
> >> +	for (int i = 0; i < size; i++) {
> >> +		if (msg_recv.data.pbytes[i] != buff->msg.data.pbytes[i]) {
> >> +			tst_res(TFAIL, "Received wrong data at index %d: %x != %x", i,
> >> +				msg_recv.data.pbytes[i],
> >> +				buff->msg.data.pbytes[i]);
> >> +
> >> +			goto exit;
> >> +		}
> >>   	}
> >>   
> >> -	tst_resm(TPASS, "Test ran successfully!");
> >> +	tst_res(TPASS, "Received correct data");
> > This spams the test output with a few hundreds of lines of output, which
> > is known to choke test runners. For this case we should probably output
> > one single TPASS at the end of the test.
> >
> > Also this seems to be a common pattern, so we may as well add a function
> > into the test library that would produce TPASS unless we have seen a
> > FAIL/BROK/WARN. Or maybe just a function that would return sum of the
> > result counters so that we can do:
> >
> > 	if (tst_get_res(TFAIL|TBROK|TWARN))
> > 		tst_res(TPASS, "All data were received correctly");
> >
> >
> Isn't it like this already?

Not at all, test that does not report any results is supposed to be
broken and reports TBROK. The reasoning is that test results have to be
reported explicitly.

And currently we do not have any API that would allow the test to get
the value of the result reporting counters, so testcases that want to
report PASS/FAIL at the end of the test have to keep the track
themselves, usually by having a page of shared memory with a coutner. So
perhaps it would make sense to add a function that would return the
value of the result counters so that we can use them to report TPASS if
no errors were found during the test iteration.
diff mbox series

Patch

diff --git a/runtest/syscalls b/runtest/syscalls
index 7794f1465..ef4b2bcef 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -866,12 +866,10 @@  msgctl03 msgctl03
 msgctl04 msgctl04
 msgctl05 msgctl05
 msgctl06 msgctl06
-msgstress01 msgstress01
-msgstress02 msgstress02
-msgstress03 msgstress03
-msgstress04 msgstress04
 msgctl12 msgctl12
 
+msgstress01 msgstress01
+
 msgget01 msgget01
 msgget02 msgget02
 msgget03 msgget03
diff --git a/runtest/syscalls-ipc b/runtest/syscalls-ipc
index df41140a7..cd41e61c1 100644
--- a/runtest/syscalls-ipc
+++ b/runtest/syscalls-ipc
@@ -4,12 +4,10 @@  msgctl03 msgctl03
 msgctl04 msgctl04
 msgctl05 msgctl05
 msgctl06 msgctl06
-msgstress01 msgstress01
-msgstress02 msgstress02
-msgstress03 msgstress03
-msgstress04 msgstress04
 msgctl12 msgctl12
 
+msgstress01 msgstress01
+
 msgget01 msgget01
 msgget02 msgget02
 msgget03 msgget03
diff --git a/testcases/kernel/syscalls/ipc/msgstress/.gitignore b/testcases/kernel/syscalls/ipc/msgstress/.gitignore
index a8f675399..fe9780693 100644
--- a/testcases/kernel/syscalls/ipc/msgstress/.gitignore
+++ b/testcases/kernel/syscalls/ipc/msgstress/.gitignore
@@ -1,4 +1 @@ 
 /msgstress01
-/msgstress02
-/msgstress03
-/msgstress04
diff --git a/testcases/kernel/syscalls/ipc/msgstress/Makefile b/testcases/kernel/syscalls/ipc/msgstress/Makefile
index b821bda01..442eb87d5 100644
--- a/testcases/kernel/syscalls/ipc/msgstress/Makefile
+++ b/testcases/kernel/syscalls/ipc/msgstress/Makefile
@@ -3,10 +3,5 @@ 
 
 top_srcdir              ?= ../../../../..
 
-LTPLIBS = ltpipc
-
 include $(top_srcdir)/include/mk/testcases.mk
-
-LTPLDLIBS  += -lltpipc
-
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/ipc/msgstress/msgstress01.c b/testcases/kernel/syscalls/ipc/msgstress/msgstress01.c
index 84e338437..6ec2e012a 100644
--- a/testcases/kernel/syscalls/ipc/msgstress/msgstress01.c
+++ b/testcases/kernel/syscalls/ipc/msgstress/msgstress01.c
@@ -1,301 +1,221 @@ 
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
- * Copyright (c) International Business Machines  Corp., 2002
- *
- * This program is free software;  you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY;  without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program;  if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * 06/30/2001   Port to Linux   nsharoff@us.ibm.com
- * 11/06/2002   Port to LTP     dbarrera@us.ibm.com
+ * Copyright (c) International Business Machines Corp., 2002
+ *   06/30/2001   Port to Linux   nsharoff@us.ibm.com
+ *   11/11/2002   Port to LTP     dbarrera@us.ibm.com
+ * Copyright (C) 2024 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
  */
 
 /*
- * Get and manipulate a message queue.
+ * [Description]
+ *
+ * Stress test for SysV IPC. We send multiple messages at the same time,
+ * checking that we are not loosing any byte once we receive the messages
+ * from multiple children.
+ *
+ * The number of messages to send is determined by the free slots available
+ * in SysV IPC and the available number of children which can be spawned by
+ * the process.
  */
 
-#define _XOPEN_SOURCE 500
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
 #include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <values.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include "test.h"
-#include "ipcmsg.h"
-#include "libmsgctl.h"
-
-char *TCID = "msgstress01";
-int TST_TOTAL = 1;
-
-#ifndef CONFIG_COLDFIRE
-#define MAXNPROCS	1000000	/* This value is set to an arbitrary high limit. */
-#else
-#define MAXNPROCS	 100000	/* Coldfire can't deal with 1000000 */
-#endif
-#define MAXNREPS	100000
-
-static key_t keyarray[MAXNPROCS];
-static int pidarray[MAXNPROCS];
-static int tid;
-static int MSGMNI, nprocs, nreps;
-static int procstat;
-static int mykid;
-
-void setup(void);
-void cleanup(void);
-
-static int dotest(key_t key, int child_process);
-static void sig_handler();
-
-static char *opt_nprocs;
-static char *opt_nreps;
-
-static option_t options[] = {
-	{"n:", NULL, &opt_nprocs},
-	{"l:", NULL, &opt_nreps},
-	{NULL, NULL, NULL},
+#include "tst_safe_sysv_ipc.h"
+#include "tst_safe_stdio.h"
+#include "tst_test.h"
+
+#define SYSVIPC_TOTAL "/proc/sys/kernel/msgmni"
+#define SYSVIPC_USED "/proc/sysvipc/msg"
+#define KEY_VAL0 154326L
+#define MSGTYPE 10
+
+struct sysv_msg {
+	long type;
+	struct {
+		char len;
+		char pbytes[99];
+	} data;
 };
 
-static void usage(void)
+struct sysv_data {
+	int id;
+	struct sysv_msg msg;
+};
+
+static char *str_num_messages;
+static int num_messages = 1000;
+
+static struct sysv_data *ipc_data;
+static int ipc_data_len;
+
+static int get_used_sysvipc(void)
 {
-	printf("  -n      Number of processes\n");
-	printf("  -l      Number of iterations\n");
+	FILE *fp;
+	int used = -1;
+	char buf[BUFSIZ];
+
+	fp = SAFE_FOPEN(SYSVIPC_USED, "r");
+
+	while (fgets(buf, BUFSIZ, fp) != NULL)
+		used++;
+
+	SAFE_FCLOSE(fp);
+
+	if (used < 0)
+		tst_brk(TBROK, "Can't read %s to get used sysvipc resource", SYSVIPC_USED);
+
+	return used;
 }
 
-int main(int argc, char **argv)
+static void reset_messages(void)
 {
-	int i, j, ok, pid;
-	int count, status;
-	struct sigaction act;
+	ipc_data_len = 0;
+	memset(ipc_data, 0, sizeof(struct sysv_data) * num_messages);
 
-	tst_parse_opts(argc, argv, options, usage);
+	for (int i = 0; i < num_messages; i++)
+		ipc_data[i].id = -1;
+}
 
-	setup();
+static int create_message(const int id)
+{
+	int pos = ipc_data_len;
+	struct sysv_data *buff = ipc_data + pos;
 
-	nreps = MAXNREPS;
-	nprocs = MSGMNI;
+	buff->id = id;
+	buff->msg.type = MSGTYPE;
+	buff->msg.data.len = (rand() % 99) + 1;
 
-	if (opt_nreps) {
-		nreps = atoi(opt_nreps);
-		if (nreps > MAXNREPS) {
-			tst_resm(TINFO,
-				 "Requested number of iterations too large, "
-				 "setting to Max. of %d", MAXNREPS);
-			nreps = MAXNREPS;
-		}
-	}
+	for (int i = 0; i < buff->msg.data.len; i++)
+		buff->msg.data.pbytes[i] = rand() % 255;
 
-	if (opt_nprocs) {
-		nprocs = atoi(opt_nprocs);
-		if (nprocs > MSGMNI) {
-			tst_resm(TINFO,
-				 "Requested number of processes too large, "
-				 "setting to Max. of %d", MSGMNI);
-			nprocs = MSGMNI;
-		}
-	}
+	ipc_data_len++;
 
-	srand(getpid());
-	tid = -1;
+	return pos;
+}
 
-	/* Setup signal handling routine */
-	memset(&act, 0, sizeof(act));
-	act.sa_handler = sig_handler;
-	sigemptyset(&act.sa_mask);
-	sigaddset(&act.sa_mask, SIGTERM);
-	if (sigaction(SIGTERM, &act, NULL) < 0) {
-		tst_brkm(TFAIL, NULL, "Sigset SIGTERM failed");
-	}
-	/* Set up array of unique keys for use in allocating message
-	 * queues
-	 */
-	for (i = 0; i < nprocs; i++) {
-		ok = 1;
-		do {
-			/* Get random key */
-			keyarray[i] = (key_t) rand();
-			/* Make sure key is unique and not private */
-			if (keyarray[i] == IPC_PRIVATE) {
-				ok = 0;
-				continue;
-			}
-			for (j = 0; j < i; j++) {
-				if (keyarray[j] == keyarray[i]) {
-					ok = 0;
-					break;
-				}
-				ok = 1;
-			}
-		} while (ok == 0);
-	}
+static void reader(const int id)
+{
+	int size;
+	struct sysv_msg msg_recv;
+	struct sysv_data *buff = NULL;
 
-	/* Fork a number of processes, each of which will
-	 * create a message queue with one reader/writer
-	 * pair which will read and write a number (iterations)
-	 * of random length messages with specific values.
-	 */
+	memset(&msg_recv, 0, sizeof(struct sysv_msg));
 
-	for (i = 0; i < nprocs; i++) {
-		fflush(stdout);
-		if ((pid = FORK_OR_VFORK()) < 0) {
-			tst_brkm(TFAIL,
-				 NULL,
-				 "\tFork failed (may be OK if under stress)");
-		}
-		/* Child does this */
-		if (pid == 0) {
-			procstat = 1;
-			exit(dotest(keyarray[i], i));
+	size = SAFE_MSGRCV(id, &msg_recv, 100, MSGTYPE, 0);
+
+	for (int i = 0; i < ipc_data_len; i++) {
+		if (ipc_data[i].id == id) {
+			buff = ipc_data + i;
+			break;
 		}
-		pidarray[i] = pid;
 	}
 
-	count = 0;
-	while (1) {
-		if ((wait(&status)) > 0) {
-			if (status >> 8 != 0) {
-				tst_brkm(TFAIL, NULL,
-					 "Child exit status = %d",
-					 status >> 8);
-			}
-			count++;
-		} else {
-			if (errno != EINTR) {
-				break;
-			}
-#ifdef DEBUG
-			tst_resm(TINFO, "Signal detected during wait");
-#endif
-		}
+	if (!buff) {
+		tst_brk(TBROK, "Can't find original message. This is a test issue!");
+		return;
 	}
-	/* Make sure proper number of children exited */
-	if (count != nprocs) {
-		tst_brkm(TFAIL,
-			 NULL,
-			 "Wrong number of children exited, Saw %d, Expected %d",
-			 count, nprocs);
+
+	TST_EXP_EQ_LI(msg_recv.type, buff->msg.type);
+	TST_EXP_EQ_LI(msg_recv.data.len, buff->msg.data.len);
+
+	for (int i = 0; i < size; i++) {
+		if (msg_recv.data.pbytes[i] != buff->msg.data.pbytes[i]) {
+			tst_res(TFAIL, "Received wrong data at index %d: %x != %x", i,
+				msg_recv.data.pbytes[i],
+				buff->msg.data.pbytes[i]);
+
+			goto exit;
+		}
 	}
 
-	tst_resm(TPASS, "Test ran successfully!");
+	tst_res(TPASS, "Received correct data");
 
-	cleanup();
-	tst_exit();
+exit:
+	buff->id = -1;
 }
 
-static int dotest(key_t key, int child_process)
+static void run(void)
 {
-	int id, pid;
-	int ret, status;
+	int id, pos;
 
-	sighold(SIGTERM);
-	TEST(msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR));
-	if (TEST_RETURN < 0) {
-		printf("msgget() error in child %d: %s\n",
-			child_process, strerror(TEST_ERRNO));
+	reset_messages();
 
-		return FAIL;
-	}
-	tid = id = TEST_RETURN;
-	sigrelse(SIGTERM);
-
-	fflush(stdout);
-	if ((pid = FORK_OR_VFORK()) < 0) {
-		printf("\tFork failed (may be OK if under stress)\n");
-		TEST(msgctl(tid, IPC_RMID, 0));
-		if (TEST_RETURN < 0) {
-			printf("mscgtl() error in cleanup: %s\n",
-				strerror(TEST_ERRNO));
+	for (int i = 0; i < num_messages; i++) {
+		id = SAFE_MSGGET(KEY_VAL0 + i, IPC_CREAT | 0600);
+		pos = create_message(id);
+
+		if (!SAFE_FORK()) {
+			struct sysv_data *buff = &ipc_data[pos];
+
+			SAFE_MSGSND(id, &buff->msg, 100, 0);
+			return;
+		}
+
+		if (!SAFE_FORK()) {
+			reader(id);
+			return;
 		}
-		return FAIL;
-	}
-	/* Child does this */
-	if (pid == 0)
-		exit(doreader(key, id, 1, child_process, nreps));
-	/* Parent does this */
-	mykid = pid;
-	procstat = 2;
-	ret = dowriter(key, id, 1, child_process, nreps);
-	wait(&status);
-
-	if (ret != PASS)
-		exit(FAIL);
-
-	if ((!WIFEXITED(status) || (WEXITSTATUS(status) != PASS)))
-		exit(FAIL);
-
-	TEST(msgctl(id, IPC_RMID, 0));
-	if (TEST_RETURN < 0) {
-		printf("msgctl() errno %d: %s\n",
-			TEST_ERRNO, strerror(TEST_ERRNO));
-
-		return FAIL;
 	}
-	return PASS;
 }
 
-static void sig_handler(void)
+static void setup(void)
 {
-}
+	int total_msg;
+	int avail_msg;
+	int free_msgs;
+	int free_pids;
 
-void setup(void)
-{
-	int nr_msgqs;
+	srand(time(0));
+
+	SAFE_FILE_SCANF(SYSVIPC_TOTAL, "%i", &total_msg);
 
-	tst_tmpdir();
+	free_msgs = total_msg - get_used_sysvipc();
 
-	tst_sig(FORK, DEF_HANDLER, cleanup);
+	/* We remove 10% of free pids, just to be sure
+	 * we won't saturate the sysyem with processes.
+	 */
+	free_pids = tst_get_free_pids() / 2.1;
 
-	TEST_PAUSE;
+	avail_msg = MIN(free_msgs, free_pids);
+	if (!avail_msg)
+		tst_brk(TCONF, "Unavailable messages slots");
 
-	nr_msgqs = get_max_msgqueues();
-	if (nr_msgqs < 0)
-		cleanup();
+	tst_res(TINFO, "Available messages slots: %d", avail_msg);
 
-	nr_msgqs -= get_used_msgqueues();
-	if (nr_msgqs <= 0) {
-		tst_resm(TBROK,
-			 "Max number of message queues already used, cannot create more.");
-		cleanup();
-	}
+	if (tst_parse_int(str_num_messages, &num_messages, 1, avail_msg))
+		tst_brk(TBROK, "Invalid number of messages '%s'", str_num_messages);
 
-	/*
-	 * Since msgmni scales to the memory size, it may reach huge values
-	 * that are not necessary for this test.
-	 * That's why we define NR_MSGQUEUES as a high boundary for it.
-	 */
-	MSGMNI = MIN(nr_msgqs, NR_MSGQUEUES);
+	ipc_data = SAFE_MMAP(
+		NULL,
+		sizeof(struct sysv_data) * num_messages,
+		PROT_READ | PROT_WRITE,
+		MAP_SHARED | MAP_ANONYMOUS,
+		-1, 0);
+
+	reset_messages();
 }
 
-void cleanup(void)
+static void cleanup(void)
 {
-	int status;
+	if (!ipc_data)
+		return;
 
-#ifdef DEBUG
-	tst_resm(TINFO, "Removing the message queue");
-#endif
-	(void)msgctl(tid, IPC_RMID, NULL);
-	if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) {
-		(void)msgctl(tid, IPC_RMID, NULL);
-		tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
+	for (int pos = 0; pos < num_messages; pos++) {
+		struct sysv_data *buff = &ipc_data[pos];
 
+		if (buff->id != -1)
+			SAFE_MSGCTL(buff->id, IPC_RMID, NULL);
 	}
 
-	tst_rmdir();
+	SAFE_MUNMAP(ipc_data, sizeof(struct sysv_data) * num_messages);
 }
+
+static struct tst_test test = {
+	.test_all = run,
+	.setup = setup,
+	.cleanup = cleanup,
+	.forks_child = 1,
+	.options = (struct tst_option[]) {
+		{"n:", &str_num_messages, "Number of messages to send (default: 1000)"},
+		{},
+	},
+};
diff --git a/testcases/kernel/syscalls/ipc/msgstress/msgstress02.c b/testcases/kernel/syscalls/ipc/msgstress/msgstress02.c
deleted file mode 100644
index a0f894b05..000000000
--- a/testcases/kernel/syscalls/ipc/msgstress/msgstress02.c
+++ /dev/null
@@ -1,408 +0,0 @@ 
-/*
- * Copyright (c) International Business Machines  Corp., 2002
- *
- * This program is free software;  you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY;  without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program;  if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * 06/30/2001   Port to Linux   nsharoff@us.ibm.com
- * 11/11/2002   Port to LTP     dbarrera@us.ibm.com
- */
-
-/*
- * Get and manipulate a message queue.
- */
-
-#define _XOPEN_SOURCE 500
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "test.h"
-#include "ipcmsg.h"
-#include "libmsgctl.h"
-
-char *TCID = "msgstress02";
-int TST_TOTAL = 1;
-
-#define MAXNREPS	1000
-#ifndef CONFIG_COLDFIRE
-#define MAXNPROCS	 1000000	/* This value is set to an arbitrary high limit. */
-#else
-#define MAXNPROCS	 100000	/* Coldfire can't deal with 1000000 */
-#endif
-#define MAXNKIDS	10
-
-static key_t keyarray[MAXNPROCS];
-static int pidarray[MAXNPROCS];
-static int rkidarray[MAXNKIDS];
-static int wkidarray[MAXNKIDS];
-static int tid;
-static int nprocs, nreps, nkids, MSGMNI;
-static int procstat;
-
-void setup(void);
-void cleanup(void);
-
-static void term(int);
-static int dotest(key_t, int);
-static void cleanup_msgqueue(int i, int tid);
-
-static char *opt_nprocs;
-static char *opt_nkids;
-static char *opt_nreps;
-
-static option_t options[] = {
-	{"n:", NULL, &opt_nprocs},
-	{"c:", NULL, &opt_nkids},
-	{"l:", NULL, &opt_nreps},
-	{NULL, NULL, NULL},
-};
-
-static void usage(void)
-{
-	printf("  -n      Number of processes\n");
-	printf("  -c      Number of read/write child pairs\n");
-	printf("  -l      Number of iterations\n");
-}
-
-int main(int argc, char **argv)
-{
-	int i, j, ok, pid;
-	int count, status;
-
-	tst_parse_opts(argc, argv, options, usage);
-
-	setup();
-
-	nreps = MAXNREPS;
-	nprocs = MSGMNI;
-	nkids = MAXNKIDS;
-
-	if (opt_nreps) {
-		nreps = atoi(opt_nreps);
-		if (nreps > MAXNREPS) {
-			tst_resm(TINFO,
-				 "Requested number of iterations too large, "
-				 "setting to Max. of %d", MAXNREPS);
-			nreps = MAXNREPS;
-		}
-	}
-
-	if (opt_nprocs) {
-		nprocs = atoi(opt_nprocs);
-		if (nprocs > MSGMNI) {
-			tst_resm(TINFO,
-				 "Requested number of processes too large, "
-				 "setting to Max. of %d", MSGMNI);
-			nprocs = MSGMNI;
-		}
-	}
-
-	if (opt_nkids) {
-		nkids = atoi(opt_nkids);
-		if (nkids > MAXNKIDS) {
-			tst_resm(TINFO,
-				 "Requested number of read/write pairs too "
-				 "large, setting to Max. of %d", MAXNKIDS);
-			nkids = MAXNKIDS;
-		}
-	}
-
-	procstat = 0;
-	srand48((unsigned)getpid() + (unsigned)(getppid() << 16));
-	tid = -1;
-
-	/* Setup signal handleing routine */
-	if (sigset(SIGTERM, term) == SIG_ERR) {
-		tst_brkm(TFAIL, NULL, "Sigset SIGTERM failed");
-	}
-	/* Set up array of unique keys for use in allocating message
-	 * queues
-	 */
-	for (i = 0; i < nprocs; i++) {
-		ok = 1;
-		do {
-			/* Get random key */
-			keyarray[i] = (key_t) lrand48();
-			/* Make sure key is unique and not private */
-			if (keyarray[i] == IPC_PRIVATE) {
-				ok = 0;
-				continue;
-			}
-			for (j = 0; j < i; j++) {
-				if (keyarray[j] == keyarray[i]) {
-					ok = 0;
-					break;
-				}
-				ok = 1;
-			}
-		} while (ok == 0);
-	}
-	/* Fork a number of processes (nprocs), each of which will
-	 * create a message queue with several (nkids) reader/writer
-	 * pairs which will read and write a number (iterations)
-	 * of random length messages with specific values (keys).
-	 */
-
-	for (i = 0; i < nprocs; i++) {
-		fflush(stdout);
-		if ((pid = FORK_OR_VFORK()) < 0) {
-			tst_brkm(TFAIL,
-				 NULL,
-				 "\tFork failed (may be OK if under stress)");
-		}
-		/* Child does this */
-		if (pid == 0) {
-			procstat = 1;
-			exit(dotest(keyarray[i], i));
-		}
-		pidarray[i] = pid;
-	}
-
-	count = 0;
-	while (1) {
-		if ((wait(&status)) > 0) {
-			if (status >> 8 != PASS) {
-				tst_brkm(TFAIL, NULL,
-					 "Child exit status = %d",
-					 status >> 8);
-			}
-			count++;
-		} else {
-			if (errno != EINTR) {
-				break;
-			}
-#ifdef DEBUG
-			tst_resm(TINFO, "Signal detected during wait");
-#endif
-		}
-	}
-	/* Make sure proper number of children exited */
-	if (count != nprocs) {
-		tst_brkm(TFAIL,
-			 NULL,
-			 "Wrong number of children exited, Saw %d, Expected %d",
-			 count, nprocs);
-	}
-
-	tst_resm(TPASS, "Test ran successfully!");
-
-	cleanup();
-	tst_exit();
-}
-
-static void cleanup_msgqueue(int i, int tid)
-{
-	/*
-	 * Decrease the value of i by 1 because it
-	 * is getting incremented even if the fork
-	 * is failing.
-	 */
-
-	i--;
-	/*
-	 * Kill all children & free message queue.
-	 */
-	for (; i >= 0; i--) {
-		(void)kill(rkidarray[i], SIGKILL);
-		(void)kill(wkidarray[i], SIGKILL);
-	}
-
-	if (msgctl(tid, IPC_RMID, 0) < 0) {
-		tst_brkm(TFAIL | TERRNO, NULL, "Msgctl error in cleanup");
-	}
-}
-
-static int dotest(key_t key, int child_process)
-{
-	int id, pid;
-	int i, count, status, exit_status;
-
-	sighold(SIGTERM);
-	if ((id = msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR)) < 0) {
-		printf("msgget() error in child %d: %s\n",
-			child_process, strerror(errno));
-		return FAIL;
-	}
-	tid = id;
-	sigrelse(SIGTERM);
-
-	exit_status = PASS;
-
-	for (i = 0; i < nkids; i++) {
-		fflush(stdout);
-		if ((pid = FORK_OR_VFORK()) < 0) {
-			printf("Fork failure in the first child of child group %d\n",
-				child_process);
-			cleanup_msgqueue(i, tid);
-			return FAIL;
-		}
-		/* First child does this */
-		if (pid == 0) {
-			procstat = 2;
-			exit(doreader(key, tid, getpid(),
-					child_process, nreps));
-		}
-		rkidarray[i] = pid;
-		fflush(stdout);
-		if ((pid = FORK_OR_VFORK()) < 0) {
-			printf("Fork failure in the second child of child group %d\n",
-				child_process);
-			/*
-			 * Kill the reader child process
-			 */
-			(void)kill(rkidarray[i], SIGKILL);
-
-			cleanup_msgqueue(i, tid);
-			return FAIL;
-		}
-		/* Second child does this */
-		if (pid == 0) {
-			procstat = 2;
-			exit(dowriter(key, tid, rkidarray[i],
-					child_process, nreps));
-		}
-		wkidarray[i] = pid;
-	}
-	/* Parent does this */
-	count = 0;
-	while (1) {
-		if ((wait(&status)) > 0) {
-			if (status >> 8 != PASS) {
-				printf("Child exit status = %d from child group %d\n",
-					status >> 8, child_process);
-				for (i = 0; i < nkids; i++) {
-					kill(rkidarray[i], SIGTERM);
-					kill(wkidarray[i], SIGTERM);
-				}
-				if (msgctl(tid, IPC_RMID, 0) < 0) {
-					printf("msgctl() error: %s\n",
-						strerror(errno));
-				}
-				return FAIL;
-			}
-			count++;
-		} else {
-			if (errno != EINTR) {
-				break;
-			}
-		}
-	}
-	/* Make sure proper number of children exited */
-	if (count != (nkids * 2)) {
-		printf("Wrong number of children exited in child group %d, saw %d, expected %d\n",
-			child_process, count, (nkids * 2));
-		if (msgctl(tid, IPC_RMID, 0) < 0) {
-			printf("msgctl() error: %s\n", strerror(errno));
-		}
-		return FAIL;
-	}
-	if (msgctl(id, IPC_RMID, 0) < 0) {
-		printf("msgctl() failure in child group %d: %s\n",
-			child_process, strerror(errno));
-		return FAIL;
-	}
-	return exit_status;
-}
-
-static void term(int sig LTP_ATTRIBUTE_UNUSED)
-{
-	int i;
-
-	if (procstat == 0) {
-#ifdef DEBUG
-		tst_resm(TINFO, "SIGTERM signal received, test killing kids");
-#endif
-		for (i = 0; i < nprocs; i++) {
-			if (pidarray[i] > 0) {
-				if (kill(pidarray[i], SIGTERM) < 0) {
-					printf("Kill failed to kill child %d",
-						i);
-					exit(FAIL);
-				}
-			}
-		}
-		return;
-	}
-
-	if (procstat == 2) {
-		fflush(stdout);
-		exit(PASS);
-	}
-
-	if (tid == -1) {
-		exit(FAIL);
-	}
-	for (i = 0; i < nkids; i++) {
-		if (rkidarray[i] > 0)
-			kill(rkidarray[i], SIGTERM);
-		if (wkidarray[i] > 0)
-			kill(wkidarray[i], SIGTERM);
-	}
-}
-
-void setup(void)
-{
-	int nr_msgqs;
-
-	tst_tmpdir();
-
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	nr_msgqs = get_max_msgqueues();
-	if (nr_msgqs < 0)
-		cleanup();
-
-	nr_msgqs -= get_used_msgqueues();
-	if (nr_msgqs <= 0) {
-		tst_resm(TBROK,
-			 "Max number of message queues already used, cannot create more.");
-		cleanup();
-	}
-
-	/*
-	 * Since msgmni scales to the memory size, it may reach huge values
-	 * that are not necessary for this test.
-	 * That's why we define NR_MSGQUEUES as a high boundary for it.
-	 */
-	MSGMNI = MIN(nr_msgqs, NR_MSGQUEUES);
-}
-
-void cleanup(void)
-{
-	int status;
-
-#ifdef DEBUG
-	tst_resm(TINFO, "Removing the message queue");
-#endif
-	fflush(stdout);
-	(void)msgctl(tid, IPC_RMID, NULL);
-	if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) {
-		(void)msgctl(tid, IPC_RMID, NULL);
-		tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
-
-	}
-
-	fflush(stdout);
-	tst_rmdir();
-}
diff --git a/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c b/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c
deleted file mode 100644
index aa37d9058..000000000
--- a/testcases/kernel/syscalls/ipc/msgstress/msgstress03.c
+++ /dev/null
@@ -1,299 +0,0 @@ 
-/*
- * Copyright (c) International Business Machines  Corp., 2002
- *
- * This program is free software;  you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY;  without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program;  if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * 06/30/2001   Port to Linux   nsharoff@us.ibm.com
- * 11/06/2002   Port to LTP     dbarrera@us.ibm.com
- */
-
-/*
- * Get and manipulate a message queue.
- * Same as msgstress01 but gets the actual msgmni value under procfs.
- */
-
-#define _XOPEN_SOURCE 500
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <values.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include "test.h"
-#include "ipcmsg.h"
-#include "libmsgctl.h"
-
-char *TCID = "msgstress03";
-int TST_TOTAL = 1;
-
-#define MAXNPROCS	10000	/*These should be sufficient */
-#define MAXNREPS	10000	/*Else they srewup the system un-necessarily */
-
-static key_t keyarray[MAXNPROCS];
-static int pidarray[MAXNPROCS];
-static int tid;
-static int MSGMNI, nprocs, nreps;
-static int procstat;
-static int mykid;
-
-void setup(void);
-void cleanup(void);
-
-static int dotest(key_t key, int child_process);
-static void sig_handler(int signo);
-
-static char *opt_nprocs;
-static char *opt_nreps;
-
-static option_t options[] = {
-	{"n:", NULL, &opt_nprocs},
-	{"l:", NULL, &opt_nreps},
-	{NULL, NULL, NULL},
-};
-
-static void usage(void)
-{
-	printf("  -n      Number of processes\n");
-	printf("  -l      Number of iterations\n");
-}
-
-int main(int argc, char **argv)
-{
-	int i, j, ok, pid, free_pids;
-	int count, status;
-	struct sigaction act;
-
-	tst_parse_opts(argc, argv, options, usage);
-
-	setup();
-
-	nreps = MAXNREPS;
-	nprocs = MSGMNI;
-
-	if (opt_nreps) {
-		nreps = atoi(opt_nreps);
-		if (nreps > MAXNREPS) {
-			tst_resm(TINFO,
-				 "Requested number of iterations too large, "
-				 "setting to Max. of %d", MAXNREPS);
-			nreps = MAXNREPS;
-		}
-	}
-
-	if (opt_nprocs) {
-		nprocs = atoi(opt_nprocs);
-		if (nprocs > MSGMNI) {
-			tst_resm(TINFO,
-				 "Requested number of processes too large, "
-				 "setting to Max. of %d", MSGMNI);
-			nprocs = MSGMNI;
-		}
-	}
-
-	free_pids = tst_get_free_pids(cleanup);
-	/* Each forked child forks once, take it into account here. */
-	if (nprocs * 2 >= free_pids) {
-		tst_resm(TINFO,
-			 "Requested number of processes higher than limit (%d > %d), "
-			 "setting to %d", nprocs * 2, free_pids, free_pids);
-		nprocs = free_pids / 2;
-	}
-
-	srand(getpid());
-	tid = -1;
-
-	/* Setup signal handling routine */
-	memset(&act, 0, sizeof(act));
-	act.sa_handler = sig_handler;
-	sigemptyset(&act.sa_mask);
-	sigaddset(&act.sa_mask, SIGTERM);
-	if (sigaction(SIGTERM, &act, NULL) < 0) {
-		tst_brkm(TFAIL, NULL, "Sigset SIGTERM failed");
-	}
-	/* Set up array of unique keys for use in allocating message
-	 * queues
-	 */
-	for (i = 0; i < nprocs; i++) {
-		ok = 1;
-		do {
-			/* Get random key */
-			keyarray[i] = (key_t) rand();
-			/* Make sure key is unique and not private */
-			if (keyarray[i] == IPC_PRIVATE) {
-				ok = 0;
-				continue;
-			}
-			for (j = 0; j < i; j++) {
-				if (keyarray[j] == keyarray[i]) {
-					ok = 0;
-					break;
-				}
-				ok = 1;
-			}
-		} while (ok == 0);
-	}
-
-	/* Fork a number of processes, each of which will
-	 * create a message queue with one reader/writer
-	 * pair which will read and write a number (iterations)
-	 * of random length messages with specific values.
-	 */
-
-	for (i = 0; i < nprocs; i++) {
-		fflush(stdout);
-		if ((pid = FORK_OR_VFORK()) < 0) {
-			tst_brkm(TFAIL,
-				 NULL,
-				 "\tFork failed (may be OK if under stress)");
-		}
-		/* Child does this */
-		if (pid == 0) {
-			procstat = 1;
-			exit(dotest(keyarray[i], i));
-		}
-		pidarray[i] = pid;
-	}
-
-	count = 0;
-	while (1) {
-		if ((wait(&status)) > 0) {
-			if (status >> 8 != 0) {
-				tst_brkm(TFAIL, NULL,
-					 "Child exit status = %d",
-					 status >> 8);
-			}
-			count++;
-		} else {
-			if (errno != EINTR) {
-				break;
-			}
-#ifdef DEBUG
-			tst_resm(TINFO, "Signal detected during wait");
-#endif
-		}
-	}
-	/* Make sure proper number of children exited */
-	if (count != nprocs) {
-		tst_brkm(TFAIL,
-			 NULL,
-			 "Wrong number of children exited, Saw %d, Expected %d",
-			 count, nprocs);
-	}
-
-	tst_resm(TPASS, "Test ran successfully!");
-
-	cleanup();
-	tst_exit();
-}
-
-static int dotest(key_t key, int child_process)
-{
-	int id, pid;
-	int ret, status;
-
-	sighold(SIGTERM);
-	TEST(msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR));
-	if (TEST_RETURN < 0) {
-		printf("msgget() error in child %d: %s\n",
-			child_process, strerror(TEST_ERRNO));
-		return FAIL;
-	}
-	tid = id = TEST_RETURN;
-	sigrelse(SIGTERM);
-
-	fflush(stdout);
-	if ((pid = FORK_OR_VFORK()) < 0) {
-		printf("Fork failed (may be OK if under stress)\n");
-		TEST(msgctl(tid, IPC_RMID, 0));
-		if (TEST_RETURN < 0) {
-			printf("msgctl() error in cleanup: %s\n",
-				strerror(TEST_ERRNO));
-		}
-		return FAIL;
-	}
-	if (pid == 0)
-		exit(doreader(key, id, 1, child_process, nreps));
-
-	mykid = pid;
-	procstat = 2;
-	ret = dowriter(key, id, 1, child_process, nreps);
-	wait(&status);
-
-	if (ret != PASS)
-		exit(FAIL);
-
-	if ((!WIFEXITED(status) || (WEXITSTATUS(status) != PASS)))
-		exit(FAIL);
-
-	TEST(msgctl(id, IPC_RMID, 0));
-	if (TEST_RETURN < 0) {
-		printf("msgctl() failed: %s\n",
-			strerror(TEST_ERRNO));
-		return FAIL;
-	}
-	return PASS;
-}
-
-static void sig_handler(int signo LTP_ATTRIBUTE_UNUSED)
-{
-}
-
-void setup(void)
-{
-	int nr_msgqs;
-
-	tst_tmpdir();
-
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-
-	TEST_PAUSE;
-
-	nr_msgqs = get_max_msgqueues();
-	if (nr_msgqs < 0)
-		cleanup();
-
-	MSGMNI = nr_msgqs - get_used_msgqueues();
-	if (MSGMNI > MAXNPROCS)
-		MSGMNI = MAXNPROCS;
-	if (MSGMNI <= 0) {
-		tst_resm(TBROK,
-			 "Max number of message queues already used, cannot create more.");
-		cleanup();
-	}
-}
-
-void cleanup(void)
-{
-	int status;
-
-#ifdef DEBUG
-	tst_resm(TINFO, "Removing the message queue");
-#endif
-	(void)msgctl(tid, IPC_RMID, NULL);
-	if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) {
-		(void)msgctl(tid, IPC_RMID, NULL);
-		tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
-
-	}
-
-	tst_rmdir();
-}
diff --git a/testcases/kernel/syscalls/ipc/msgstress/msgstress04.c b/testcases/kernel/syscalls/ipc/msgstress/msgstress04.c
deleted file mode 100644
index b9ebf9035..000000000
--- a/testcases/kernel/syscalls/ipc/msgstress/msgstress04.c
+++ /dev/null
@@ -1,444 +0,0 @@ 
-/*
- * Copyright (c) International Business Machines  Corp., 2002
- *
- * This program is free software;  you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY;  without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- * the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program;  if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * 06/30/2001   Port to Linux   nsharoff@us.ibm.com
- * 11/11/2002   Port to LTP     dbarrera@us.ibm.com
- */
-
-/*
- * Get and manipulate a message queue.
- * Same as msgstress02 but gets the actual msgmni value under procfs.
- */
-
-#define _XOPEN_SOURCE 500
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/msg.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "test.h"
-#include "ipcmsg.h"
-#include "libmsgctl.h"
-
-char *TCID = "msgstress04";
-int TST_TOTAL = 1;
-
-#define MAXNREPS	1000
-#ifndef CONFIG_COLDFIRE
-#define MAXNPROCS	 1000000	/* This value is set to an arbitrary high limit. */
-#else
-#define MAXNPROCS	 100000	/* Coldfire can't deal with 1000000 */
-#endif
-#define MAXNKIDS	10
-#define DEFNKIDS	2
-
-static int maxnkids = MAXNKIDS;	/* Used if pid_max is exceeded */
-static key_t keyarray[MAXNPROCS];
-static int pidarray[MAXNPROCS];
-static int rkidarray[MAXNKIDS];
-static int wkidarray[MAXNKIDS];
-static int tid;
-static int nprocs, nreps, nkids, MSGMNI;
-static int maxnprocs;
-static int procstat;
-
-void setup(void);
-void cleanup(void);
-
-static void term(int);
-static int dotest(key_t, int);
-static void dotest_iteration(int off);
-static void cleanup_msgqueue(int i, int tid);
-
-static char *opt_maxnprocs;
-static char *opt_nkids;
-static char *opt_nreps;
-
-static option_t options[] = {
-	{"n:", NULL, &opt_maxnprocs},
-	{"c:", NULL, &opt_nkids},
-	{"l:", NULL, &opt_nreps},
-	{NULL, NULL, NULL},
-};
-
-static void usage(void)
-{
-	printf("  -n      Number of processes\n");
-	printf("  -c      Number of read/write child pairs\n");
-	printf("  -l      Number of iterations\n");
-}
-
-
-int main(int argc, char **argv)
-{
-	int i, j, ok;
-
-	tst_parse_opts(argc, argv, options, usage);
-
-	setup();
-
-	nreps = MAXNREPS;
-	nkids = MAXNKIDS;
-
-	if (opt_nreps) {
-		nreps = atoi(opt_nreps);
-		if (nreps > MAXNREPS) {
-			tst_resm(TINFO,
-				 "Requested number of iterations too large, "
-				 "setting to Max. of %d", MAXNREPS);
-			nreps = MAXNREPS;
-		}
-	}
-
-	if (opt_nkids) {
-		nkids = atoi(opt_nkids);
-		if (nkids > MAXNKIDS) {
-			tst_resm(TINFO,
-				 "Requested number of read/write pairs too "
-				 "large, setting to Max. of %d", MAXNKIDS);
-			nkids = MAXNKIDS;
-		}
-	}
-
-
-	if (opt_maxnprocs) {
-		if (atoi(opt_maxnprocs) > maxnprocs) {
-			tst_resm(TINFO,
-				 "Requested number of processes too large, "
-				 "setting to Max. of %d", MSGMNI);
-		} else {
-			maxnprocs = atoi(opt_maxnprocs);
-		}
-	}
-
-	procstat = 0;
-	srand48((unsigned)getpid() + (unsigned)(getppid() << 16));
-	tid = -1;
-
-	/* Setup signal handling routine */
-	if (sigset(SIGTERM, term) == SIG_ERR)
-		tst_brkm(TFAIL, cleanup, "Sigset SIGTERM failed");
-
-	/* Set up array of unique keys for use in allocating message
-	 * queues
-	 */
-	for (i = 0; i < MSGMNI; i++) {
-		ok = 1;
-		do {
-			/* Get random key */
-			keyarray[i] = (key_t) lrand48();
-			/* Make sure key is unique and not private */
-			if (keyarray[i] == IPC_PRIVATE) {
-				ok = 0;
-				continue;
-			}
-			for (j = 0; j < i; j++) {
-				if (keyarray[j] == keyarray[i]) {
-					ok = 0;
-					break;
-				}
-				ok = 1;
-			}
-		} while (ok == 0);
-	}
-	/* Fork a number of processes, each of which will
-	 * create a message queue with several (nkids) reader/writer
-	 * pairs which will read and write a number (iterations)
-	 * of random length messages with specific values (keys).
-	 *
-	 * We do not fork more than maxnprocs at a time and
-	 * we fork until all the message queues get used.
-	 */
-
-	if (MSGMNI <= maxnprocs) {
-		nprocs = MSGMNI;
-		dotest_iteration(0);
-	} else {
-		for (i = 0; i < (MSGMNI / maxnprocs); i++) {
-			nprocs = maxnprocs;
-			dotest_iteration(i * maxnprocs);
-		}
-
-		nprocs = MSGMNI % maxnprocs;
-		dotest_iteration(i * maxnprocs);
-	}
-
-	tst_resm(TPASS, "Test ran successfully!");
-
-	cleanup();
-	tst_exit();
-}
-
-static void dotest_iteration(int off)
-{
-	key_t key;
-	int i, count, status;
-	pid_t pid;
-
-	memset(pidarray, 0, sizeof(pidarray));
-
-	for (i = 0; i < nprocs; i++) {
-		key = keyarray[off + i];
-
-		if ((pid = FORK_OR_VFORK()) < 0)
-			tst_brkm(TFAIL, cleanup,
-				 "Fork failed (may be OK if under stress)");
-
-		/* Child does this */
-		if (pid == 0) {
-			procstat = 1;
-			exit(dotest(key, i));
-		}
-		pidarray[i] = pid;
-	}
-
-	count = 0;
-	while (1) {
-		if ((wait(&status)) > 0) {
-			if (status >> 8 != PASS)
-				tst_brkm(TFAIL, cleanup,
-					"Child exit status = %d", status >> 8);
-			count++;
-		} else {
-			if (errno != EINTR) {
-				break;
-			}
-#ifdef DEBUG
-			tst_resm(TINFO, "Signal detected during wait");
-#endif
-		}
-	}
-	/* Make sure proper number of children exited */
-	if (count != nprocs)
-		tst_brkm(TFAIL, cleanup,
-			 "Wrong number of children exited, Saw %d, Expected %d",
-			 count, nprocs);
-}
-
-static void cleanup_msgqueue(int i, int tid)
-{
-	/*
-	 * Decrease the value of i by 1 because it
-	 * is getting incremented even if the fork
-	 * is failing.
-	 */
-
-	i--;
-	/*
-	 * Kill all children & free message queue.
-	 */
-	for (; i >= 0; i--) {
-		(void)kill(rkidarray[i], SIGKILL);
-		(void)kill(wkidarray[i], SIGKILL);
-	}
-
-	if (msgctl(tid, IPC_RMID, 0) < 0) {
-		printf("Msgctl error in cleanup_msgqueue %d\n", errno);
-		exit(FAIL);
-	}
-}
-
-static int dotest(key_t key, int child_process)
-{
-	int id, pid;
-	int i, count, status, exit_status;
-
-	sighold(SIGTERM);
-	if ((id = msgget(key, IPC_CREAT | S_IRUSR | S_IWUSR)) < 0) {
-		printf("msgget() error in child %d: %s\n",
-			child_process, strerror(errno));
-		return FAIL;
-	}
-	tid = id;
-	sigrelse(SIGTERM);
-
-	exit_status = PASS;
-
-	for (i = 0; i < nkids; i++) {
-		if ((pid = FORK_OR_VFORK()) < 0) {
-			printf("Fork failure in the first child of child group %d\n",
-				child_process);
-			cleanup_msgqueue(i, tid);
-			return FAIL;
-		}
-		/* First child does this */
-		if (pid == 0) {
-			procstat = 2;
-			exit(doreader(key, tid, getpid(),
-					child_process, nreps));
-		}
-		rkidarray[i] = pid;
-		if ((pid = FORK_OR_VFORK()) < 0) {
-			printf("Fork failure in the second child of child group %d\n",
-				child_process);
-			/*
-			 * Kill the reader child process
-			 */
-			(void)kill(rkidarray[i], SIGKILL);
-
-			cleanup_msgqueue(i, tid);
-			return FAIL;
-		}
-		/* Second child does this */
-		if (pid == 0) {
-			procstat = 2;
-			exit(dowriter(key, tid, rkidarray[i],
-					child_process, nreps));
-		}
-		wkidarray[i] = pid;
-	}
-	/* Parent does this */
-	count = 0;
-	while (1) {
-		if ((wait(&status)) > 0) {
-			if (status >> 8 != PASS) {
-				printf("Child exit status = %d from child group %d\n",
-					status >> 8, child_process);
-				for (i = 0; i < nkids; i++) {
-					kill(rkidarray[i], SIGTERM);
-					kill(wkidarray[i], SIGTERM);
-				}
-				if (msgctl(tid, IPC_RMID, 0) < 0) {
-					printf("msgctl() error: %s\n",
-						strerror(errno));
-				}
-				return FAIL;
-			}
-			count++;
-		} else {
-			if (errno != EINTR) {
-				break;
-			}
-		}
-	}
-	/* Make sure proper number of children exited */
-	if (count != (nkids * 2)) {
-		printf("Wrong number of children exited in child group %d, saw %d, expected %d\n",
-			child_process, count, (nkids * 2));
-		if (msgctl(tid, IPC_RMID, 0) < 0) {
-			printf("msgctl() error: %s\n", strerror(errno));
-		}
-		return FAIL;
-	}
-	if (msgctl(id, IPC_RMID, 0) < 0) {
-		printf("msgctl() failure in child group %d: %s\n",
-			child_process, strerror(errno));
-		return FAIL;
-	}
-	return exit_status;
-}
-
-/* ARGSUSED */
-static void term(int sig LTP_ATTRIBUTE_UNUSED)
-{
-	int i;
-
-	if (procstat == 0) {
-#ifdef DEBUG
-		tst_resm(TINFO, "SIGTERM signal received, test killing kids");
-#endif
-		for (i = 0; i < nprocs; i++) {
-			if (pidarray[i] > 0) {
-				if (kill(pidarray[i], SIGTERM) < 0) {
-					tst_resm(TBROK,
-						 "Kill failed to kill child %d",
-						 i);
-					exit(FAIL);
-				}
-			}
-		}
-		return;
-	}
-
-	if (procstat == 2) {
-		exit(PASS);
-	}
-
-	if (tid == -1) {
-		exit(FAIL);
-	}
-	for (i = 0; i < nkids; i++) {
-		if (rkidarray[i] > 0)
-			kill(rkidarray[i], SIGTERM);
-		if (wkidarray[i] > 0)
-			kill(wkidarray[i], SIGTERM);
-	}
-}
-
-void setup(void)
-{
-	int nr_msgqs, free_pids;
-
-	tst_tmpdir();
-	/* You will want to enable some signal handling so you can capture
-	 * unexpected signals like SIGSEGV.
-	 */
-	tst_sig(FORK, DEF_HANDLER, cleanup);
-
-	/* One cavet that hasn't been fixed yet.  TEST_PAUSE contains the code to
-	 * fork the test with the -c option.  You want to make sure you do this
-	 * before you create your temporary directory.
-	 */
-	TEST_PAUSE;
-
-	nr_msgqs = get_max_msgqueues();
-	if (nr_msgqs < 0)
-		tst_brkm(TBROK, cleanup, "get_max_msgqueues() failed");
-
-	MSGMNI = nr_msgqs - get_used_msgqueues();
-	if (MSGMNI <= 0)
-		tst_brkm(TBROK, cleanup,
-			 "Max number of message queues already used, cannot create more.");
-
-	tst_resm(TINFO, "Found %d available message queues", MSGMNI);
-
-	free_pids = tst_get_free_pids(cleanup);
-	/* We don't use more than a half of available pids.
-	 * For each child we fork up to 2*maxnkids grandchildren. */
-	maxnprocs = (free_pids / 2) / (1 + 2 * maxnkids);
-
-	if (!maxnprocs)
-		tst_brkm(TBROK, cleanup, "Not enough free pids");
-
-	tst_resm(TINFO, "Using upto %d pids", free_pids / 2);
-}
-
-void cleanup(void)
-{
-	int status;
-
-	/*
-	 * Remove the message queue from the system
-	 */
-#ifdef DEBUG
-	tst_resm(TINFO, "Removing the message queue");
-#endif
-	(void)msgctl(tid, IPC_RMID, NULL);
-	if ((status = msgctl(tid, IPC_STAT, NULL)) != -1) {
-		(void)msgctl(tid, IPC_RMID, NULL);
-		tst_resm(TFAIL, "msgctl(tid, IPC_RMID) failed");
-
-	}
-
-	tst_rmdir();
-}