• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017 FUJITSU LIMITED. All rights reserved.
3  * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program, if not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /*
20  * This is a regression test for a crash caused by memcg function
21  * reentrant on buggy kernel.  When doing rmdir(), a pending signal can
22  * interrupt the execution and lead to cgroup_clear_css_refs()
23  * being entered repeatedly, this results in a BUG_ON().
24  */
25 
26 #include <errno.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <sys/mount.h>
31 #include "tst_test.h"
32 
33 #define MNTPOINT	"memcg"
34 #define SUBDIR	"memcg/testdir"
35 
36 static int mount_flag;
37 static volatile int sigcounter;
38 
sighandler(int sig LTP_ATTRIBUTE_UNUSED)39 static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
40 {
41 	sigcounter++;
42 }
43 
do_child(void)44 static void do_child(void)
45 {
46 	while (1)
47 		SAFE_KILL(getppid(), SIGUSR1);
48 
49 	exit(0);
50 }
51 
do_test(void)52 static void do_test(void)
53 {
54 	pid_t cpid;
55 
56 	SAFE_SIGNAL(SIGUSR1, sighandler);
57 
58 	cpid = SAFE_FORK();
59 	if (cpid == 0)
60 		do_child();
61 
62 	while (sigcounter < 50000) {
63 		if (access(SUBDIR, F_OK))
64 			SAFE_MKDIR(SUBDIR, 0644);
65 		rmdir(SUBDIR);
66 	}
67 
68 	SAFE_KILL(cpid, SIGKILL);
69 	SAFE_WAIT(NULL);
70 
71 	tst_res(TPASS, "Bug not reproduced");
72 }
73 
setup(void)74 static void setup(void)
75 {
76 	int ret;
77 
78 	SAFE_MKDIR(MNTPOINT, 0644);
79 
80 	ret = mount("memcg", MNTPOINT, "cgroup", 0, "memory");
81 	if (ret) {
82 		if (errno == ENOENT)
83 			tst_brk(TCONF | TERRNO, "memcg not supported");
84 
85 		tst_brk(TCONF | TERRNO, "mounting memcg failed");
86 	}
87 	mount_flag = 1;
88 }
89 
cleanup(void)90 static void cleanup(void)
91 {
92 	if (!access(SUBDIR, F_OK))
93 		SAFE_RMDIR(SUBDIR);
94 
95 	if (mount_flag)
96 		tst_umount(MNTPOINT);
97 }
98 
99 static struct tst_test test = {
100 	.needs_root = 1,
101 	.needs_tmpdir = 1,
102 	.forks_child = 1,
103 	.min_kver = "2.6.24",
104 	.setup = setup,
105 	.cleanup = cleanup,
106 	.test_all = do_test,
107 };
108