Skip to contentSkip to conversation

controllers/pids: Add new testcases

PATCH Superseded Cedric Hnyda 3 participants 5 messages Nov 20, 2015 – Nov 25, 2015

v3 of 6 Superseded Latest is v6 →

lore
Share & tools
lore
#0 lore raw

PATCH v3 1/1 controllers/pids: Add new testcases

Created new testcases to test the pids controller which is used to stop any new tasks from being fork()'d after a certain limit is reached.

---
 runtest/controllers                            |  22 +++
 testcases/kernel/controllers/pids/.gitignore   |   2 +
 testcases/kernel/controllers/pids/Makefile     |  28 ++++
 testcases/kernel/controllers/pids/pids.sh      | 208 +++++++++++++++++++++++++
 testcases/kernel/controllers/pids/pids_task.c  |  63 ++++++++
 testcases/kernel/controllers/pids/pids_task2.c |  60 +++++++
 6 files changed, 383 insertions(+)
 create mode 100644 testcases/kernel/controllers/pids/.gitignore
 create mode 100644 testcases/kernel/controllers/pids/Makefile
 create mode 100644 testcases/kernel/controllers/pids/pids.sh
 create mode 100644 testcases/kernel/controllers/pids/pids_task.c
 create mode 100644 testcases/kernel/controllers/pids/pids_task2.c
runtest/controllers +22 -0
index c62bcce..254a0b0 100644
@@ -277,3 +277,25 @@ cpuset_memory_spread	cpuset_memory_spread_testset.sh
 cpuset_regression_test cpuset_regression_test.sh
 
 cgroup_xattr	cgroup_xattr
+
+pids_1_1 pids.sh 1 1
+pids_1_2 pids.sh 1 2
+pids_1_10 pids.sh 1 10
+pids_1_50 pids.sh 1 50
+pids_1_100 pids.sh 1 100
+pids_2_1 pids.sh 2 1
+pids_2_2 pids.sh 2 2
+pids_2_10 pids.sh 2 10
+pids_2_50 pids.sh 2 50
+pids_2_100 pids.sh 2 100
+pids_3_1 pids.sh 3 1
+pids_3_2 pids.sh 3 2
+pids_3_10 pids.sh 3 10
+pids_3_50 pids.sh 3 50
+pids_3_100 pids.sh 3 100
+pids_4_1 pids.sh 4 1
+pids_4_2 pids.sh 4 2
+pids_4_10 pids.sh 4 10
+pids_4_50 pids.sh 4 50
+pids_4_100 pids.sh 4 100
+pids_5_1 pids.sh 5 1
testcases/kernel/controllers/pids/.gitignore new file +2 -0
new file mode 100644
index 0000000..2a86ab2
@@ -0,0 +1,2 @@
+/pids_task
+/pids_task2
testcases/kernel/controllers/pids/Makefile new file +28 -0
new file mode 100644
index 0000000..6500363
@@ -0,0 +1,28 @@
+#
+#    Copyright (C) 2015, SUSE
+#
+#    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.
+#
+# Author: Cedric Hnyda <[email protected]>
+#
+
+top_srcdir		?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(abs_srcdir)/../Makefile.inc
+
+INSTALL_TARGETS		:= *.sh
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
testcases/kernel/controllers/pids/pids.sh new file +208 -0

208 lines not on this page · raw message

testcases/kernel/controllers/pids/pids_task.c new file +63 -0

63 lines not on this page · raw message

testcases/kernel/controllers/pids/pids_task2.c new file +60 -0

60 lines not on this page · raw message

Signature · 1 line
2.1.4
#1 lore raw

PATCH v3 1/1 controllers/pids: Add new testcases

Hi,

Quoted 5 lines · Cedric Hnyda

Created new testcases to test the pids controller which is used to stop any new tasks from being fork()'d after a certain limit is reached.

...

Quoted 10 lines

index 0000000..6500363

testcases/kernel/controllers/pids/Makefile new file +6 -0
@@ -0,0 +1,28 @@
+#
+#    Copyright (C) 2015, SUSE
+#
+#    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

testcases/kernel/controllers/pids/Makefile line 16

Quoted 10 lines
testcases/kernel/controllers/pids/Makefile new file +10 -0
+#    (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.

You could write the last paragraph as follows:

# You should have received a copy of the GNU General Public License

# along with this program. If not, see <http://www.gnu.org/licenses/>.

or, I guess, we may skip it. The main reason - the address can be changed.

testcases/kernel/controllers/pids/Makefile line 19

Quoted 3 lines
testcases/kernel/controllers/pids/Makefile new file +3 -0
+
+	while (1) {
+	}

Is it necessary to add a busy loop to completely load CPU? If we only wait, I would add a sleep, something like

while (1)

      usleep(10);

Thanks,
Alexey

#2 lore raw

PATCH v3 1/1 controllers/pids: Add new testcases

Hi,

Quoted 10 lines · Alexey Kodanev

testcases/kernel/controllers/pids/pids_task2.c line 58

Quoted 3 lines
testcases/kernel/controllers/pids/pids_task2.c new file +3 -0
+
+    while (1) {
+    }

Is it necessary to add a busy loop to completely load CPU? If we only wait, I would add a sleep, something like

while (1)

     usleep(10);

You are absolutely right, it is not needed at all to completely load CPU. Maybe it would also be better to use sleep rather than usleep.

Best regards,
Cedric

Signature · 1 line
Cedric Hnyda
#3 lore raw

PATCH v3 1/1 controllers/pids: Add new testcases

Hi!

Quoted 9 lines
Quoted 6 lines

Is it necessary to add a busy loop to completely load CPU? If we only wait, I would add a sleep, something like

while (1)

     usleep(10);

You are absolutely right, it is not needed at all to completely load CPU. Maybe it would also be better to use sleep rather than usleep.

Or we can call pause(2) which will block the process until signal arrives.

Signature · 2 lines
Cyril Hrubis
[email protected]
#4 lore raw

PATCH v3 1/1 controllers/pids: Add new testcases

In reply to Cedric Hnyda

Hi!

testcases/kernel/controllers/pids/.gitignore line 2

Quoted 5 lines
testcases/kernel/controllers/pids/.gitignore new file +2 -0
@@ -0,0 +1,2 @@
+/pids_task
+/pids_task2

I would have renamed the pids_task to pids_task1 just for consistency.

Quoted 37 lines
testcases/kernel/controllers/pids/.gitignore new file +37 -0
+cleanup()
+{
+	killall -9 pids_task2 > /dev/null
+
+	tst_resm TINFO "removing created directories"
+	rmdir $testpath
+	if [ "$mounted" -ne "1" ]; then
+		tst_resm TINFO "Umounting pids"
+		umount $mount_point
+		rmdir $mount_point
+	fi
+}
+
+setup()
+{
+	tst_require_root
+
+	exist=`grep -w pids /proc/cgroups | cut -f1`;
+	if [ "$exist" = "" ]; then
+		tst_brkm TCONF NULL "pids not supported"
+	fi
+
+	mount_point=`grep -w pids /proc/mounts | cut -f 2 | cut -d " " -f2`
+
+	if [ "$mount_point" = "" ]; then
+		mounted=0
+		mount_point=/dev/cgroup
+	fi
+
+	TST_CLEANUP=cleanup
+
+	testpath=$mount_point/ltp_$TCID
+
+	if [ "$mounted" -eq "0" ]; then
+		ROD mkdir -p $mount_point
+		ROD mount -t cgroup -o pids none $mount_point
+	fi

testcases/kernel/controllers/pids/.gitignore

Quoted 10 lines
testcases/kernel/controllers/pids/.gitignore new file +10 -0
+	ROD mkdir -p $testpath
+}
+
+case1()
+{
+	for i in `seq 1 $max`; do
+		pids_task2 "$testpath/tasks" &
+	done
+
+	sleep 1

The sleep is here to make sure all tasks are attached to the subgroup right?

If so we should rather watch the "$testpath/tasks" file if it has enough lines and sleep only if it doesn't.

Something as:

while [ $(cat "$testpath/tasks" | wc -l) -lt $max ]; do
sleep 1
done

Quoted 16 lines
testcases/kernel/controllers/pids/.gitignore new file +16 -0
+	# should return 0 because there is no limit
+	pids_task "$testpath/tasks"
+	ret=$?
+
+	killall -9 pids_task2
+
+	if [ "$ret" -eq "2" ]; then
+		tst_resm TFAIL "fork failed unexpectedly"
+	elif [ "$ret" -eq "0" ]; then
+		tst_resm TPASS "fork didn't fail"
+	else
+		tst_resm TBROK "pids_task failed"
+	fi
+}
+
+case2()

testcases/kernel/controllers/pids/.gitignore

Quoted 10 lines
testcases/kernel/controllers/pids/.gitignore new file +10 -0
+{
+	tmp=$((max - 1))
+	tst_resm TINFO "limit the number of pid to $max"
+	ROD echo $max > $testpath/pids.max
+
+	for i in `seq 1 $tmp`; do
+		pids_task2 "$testpath/tasks" &
+	done
+
+	sleep 1

Here as well.

Quoted 17 lines
testcases/kernel/controllers/pids/.gitignore new file +17 -0
+	# should return 2 because the limit of pids is reached
+	pids_task "$testpath/tasks"
+	ret=$?
+
+	killall -9 pids_task2
+
+	if [ "$ret" -eq "2" ]; then
+		tst_resm TPASS "fork failed as expected"
+	elif [ "$ret" -eq "0" ]; then
+		tst_resm TFAIL "fork didn't fail despite the limit"
+	else
+		tst_resm TBROK "pids_task failed"
+	fi
+}
+
+case3()
+{

testcases/kernel/controllers/pids/.gitignore

Quoted 10 lines
testcases/kernel/controllers/pids/.gitignore new file +10 -0
+	tmp=$((max + 1))
+	tst_resm TINFO "limit the number of avalaible pid to $tmp"
+	ROD echo $tmp > $testpath/pids.max
+
+	tmp=$((max - 2))
+	for i in `seq 1 $tmp`; do
+		pids_task2 "$testpath/tasks" &
+	done
+
+	sleep 1

And here as well. We should probably create a function to start N pids_task2 processes and to wait until they are attached.

Quoted 20 lines
testcases/kernel/controllers/pids/.gitignore new file +20 -0
+	pids_task "$testpath/tasks"
+	ret=$?
+
+	killall -9 pids_task2
+
+	if [ "$ret" -eq "2" ]; then
+		tst_resm TFAIL "fork failed unexpectedly"
+	elif [ "$ret" -eq "0" ]; then
+		tst_resm TPASS "fork worked as expected"
+	else
+		tst_resm TBROK "pids_task failed"
+	fi
+}
+
+case4()
+{
+	tst_resm TINFO "limit the number of avalaible pid to 0"
+	ROD echo 0 > $testpath/pids.max
+
+	for i in `seq 1 $max`; do

testcases/kernel/controllers/pids/.gitignore

Quoted 10 lines
testcases/kernel/controllers/pids/.gitignore new file +10 -0
+		pids_task2 "$testpath/tasks" &
+	done
+
+	sleep 1
+
+	# count the number of attached process
+	cnt=0
+	for job in `jobs -p`; do
+		cnt=$((cnt + 1))
+	done

Hmm, shouldn't cat $testpath/tasks | wc -l or jobs -p | wc -l do the same job?

Quoted 90 lines
testcases/kernel/controllers/pids/.gitignore new file +31 -0
+	killall -9 pids_task2
+
+	if [ "$cnt" -ne "$max" ]; then
+		cnt=$((max - cnt))
+		tst_resm TFAIL "$cnt process were not attached successfully"
+	else
+		tst_resm TPASS "all process were attached"
+	fi
+}
+
+case5()
+{
+	tst_resm TINFO "try to limit the number of avalaible pid to -1"
+	echo -1 > $testpath/pids.max
+
+	if [ "$?" -eq "0" ]; then
+		tst_resm TFAIL "managed to set the limit to -1"
+	else
+		tst_resm TPASS "didn't manage to set the limit to -1"
+	fi
+}
+
+setup
+
+if [ "$#" -ne "2" ]; then
+	usage
+else
+	case$caseno
+fi
+
+tst_exit
testcases/kernel/controllers/pids/pids_task.c new file +53 -0
new file mode 100644
index 0000000..a470ccf
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015 Cedric Hnyda <[email protected]>
+ *
+ * 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 would 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 the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+* Description:
+* Write the current process in argv[1]
+* and returns:
+*	-> 2 if fork fails with EAGAIN,
+*	-> 1 if there is another problem
+*	-> 0 if everything worked
+*/
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(int argc, char **argv)
+{
+	FILE *f;
+	int newpid;
+
+	if (argc != 2) {
+		fprintf(stderr, "Usage: %s /cgroup/.../tasks\n", argv[0]);
+		return 1;
+	}
+
+	f = fopen(argv[1], "a");
+	if (!f) {
+		perror("fopen failed");
+		return 1;
+	}
+
+	fprintf(f, "%i\n", getpid());
+	fclose(f);

testcases/kernel/controllers/pids/pids_task.c line 63

Quoted 10 lines
testcases/kernel/controllers/pids/pids_task.c new file +10 -0
+
+	newpid = fork();
+	if (newpid == -1 && errno == EAGAIN)
+		return 2;
+	if (newpid == -1) {
+		strerror(errno);
+		return 1;
+	}
+	return 0;
+}

Hi!

Quoted 32 lines
testcases/kernel/controllers/pids/pids_task.c new file +32 -0
+/*
+* Description:
+* Write the current process in argv[1],
+* return 1 if there is a problem in attaching the process,
+* otherwise do an infinite loop
+*/
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+	FILE *f;
+	int i;
+
+	i = 0;
+
+	if (argc != 2) {
+		fprintf(stderr, "Usage: %s /cgroup/.../tasks\n", argv[0]);
+		return 1;
+	}
+
+	f = fopen(argv[1], "a");
+	if (!f) {
+		perror("fopen failed");
+		return 1;
+	}
+

testcases/kernel/controllers/pids/pids_task.c

Quoted 10 lines
testcases/kernel/controllers/pids/pids_task.c new file +10 -0
+	i = fprintf(f, "%i\n", getpid());
+
+	fclose(f);
+	if (i < 0)
+		return 1;
+
+	while (1) {
+	}
+	return 0;
+}

Given that this process doesn't do anything else than attaching the process to the cgroup, we can simplify it to call only the pause(2) and attach the process to the cgroup in the main test script (echo $! > $testpath/tasks). That way we do not have to wait until the processes are attached in the main script and the code would be much simpler.

Signature · 2 lines
Cyril Hrubis
[email protected]