blob: 0eb4137e1f306066f7a4e7e41fa05160e819193d [file] [log] [blame]
Garrett Cooper717fb2c2010-12-08 08:44:59 -08001/*
2 * Out Of Memory when changing cpuset's mems on NUMA. There was a
3 * problem reported upstream that the allocator may see an empty
4 * nodemask when changing cpuset's mems.
5 * http://lkml.org/lkml/2010/5/4/77
6 * http://lkml.org/lkml/2010/5/4/79
7 * http://lkml.org/lkml/2010/5/4/80
8 * This test is based on the reproducers for the above issue.
9 *
10 * Copyright (C) 2010 Red Hat, Inc.
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU General Public
13 * License as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it would be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * Further, this software is distributed without any warranty that it
20 * is free of the rightful claim of any third person regarding
21 * infringement or the like. Any license provided herein, whether
22 * implied or otherwise, applies only to this software file. Patent
23 * licenses, if any, provided herein do not apply to combinations of
24 * this program with other software, or any other product whatsoever.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29 * 02110-1301, USA.
30 */
Caspar Zhang79667fa2012-03-12 14:41:46 +080031#include "config.h"
32#include <sys/types.h>
33#include <sys/mman.h>
34#include <sys/mount.h>
35#include <sys/stat.h>
36#include <sys/wait.h>
37#include <ctype.h>
38#include <err.h>
39#include <errno.h>
40#include <fcntl.h>
41#include <math.h>
42#if HAVE_NUMAIF_H
43#include <numaif.h>
44#endif
45#include <signal.h>
46#include <stdarg.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <unistd.h>
50
Garrett Cooper717fb2c2010-12-08 08:44:59 -080051#include "test.h"
Caspar Zhang79667fa2012-03-12 14:41:46 +080052#include "mem.h"
Caspar Zhanga98ac192012-08-09 14:15:41 +080053#include "numa_helper.h"
Garrett Cooper717fb2c2010-12-08 08:44:59 -080054
55char *TCID = "cpuset01";
56int TST_TOTAL = 1;
Garrett Cooper717fb2c2010-12-08 08:44:59 -080057
58#if HAVE_NUMA_H && HAVE_LINUX_MEMPOLICY_H && HAVE_NUMAIF_H \
59 && HAVE_MPOL_CONSTANTS
Garrett Cooper717fb2c2010-12-08 08:44:59 -080060volatile int end;
Caspar Zhanga98ac192012-08-09 14:15:41 +080061static int *nodes;
62static int nnodes;
Zhouping Liu8e6aafc2012-02-27 16:02:51 +080063static long ncpus;
Garrett Cooper717fb2c2010-12-08 08:44:59 -080064
Garrett Cooper717fb2c2010-12-08 08:44:59 -080065static void testcpuset(void);
66static void sighandler(int signo LTP_ATTRIBUTE_UNUSED);
Wanlong Gao354ebb42012-12-07 10:10:04 +080067static int mem_hog(void);
68static int mem_hog_cpuset(int ntasks);
Garrett Cooper717fb2c2010-12-08 08:44:59 -080069static long count_cpu(void);
Garrett Cooper717fb2c2010-12-08 08:44:59 -080070
71int main(int argc, char *argv[])
72{
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020073 const char *msg;
Garrett Cooper717fb2c2010-12-08 08:44:59 -080074
75 msg = parse_opts(argc, argv, NULL, NULL);
76 if (msg != NULL)
Garrett Cooper53740502010-12-16 00:04:01 -080077 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Zhouping Liu8e6aafc2012-02-27 16:02:51 +080078
79 ncpus = count_cpu();
Wanlong Gao354ebb42012-12-07 10:10:04 +080080 if (get_allowed_nodes_arr(NH_MEMS | NH_CPUS, &nnodes, &nodes) < 0)
81 tst_brkm(TBROK | TERRNO, NULL, "get_allowed_nodes_arr");
Zhouping Liu8e6aafc2012-02-27 16:02:51 +080082 if (nnodes <= 1)
Caspar Zhanga98ac192012-08-09 14:15:41 +080083 tst_brkm(TCONF, NULL, "requires a NUMA system.");
Zhouping Liu8e6aafc2012-02-27 16:02:51 +080084
Garrett Cooper717fb2c2010-12-08 08:44:59 -080085 setup();
86 testcpuset();
87 cleanup();
Caspar Zhangcd8fb152012-02-29 16:14:24 +080088 tst_exit();
Garrett Cooper717fb2c2010-12-08 08:44:59 -080089}
90
Zhouping Liu8e6aafc2012-02-27 16:02:51 +080091static void testcpuset(void)
Garrett Cooper717fb2c2010-12-08 08:44:59 -080092{
93 int lc;
Zhouping Liu8e6aafc2012-02-27 16:02:51 +080094 int child, i, status;
Lans Zhangcb2967b2013-04-17 16:35:27 +080095 unsigned long nmask[MAXNODES / BITS_PER_LONG] = { 0 };
Caspar Zhangff92e942012-02-29 10:58:15 +080096 char mems[BUFSIZ], buf[BUFSIZ];
Garrett Cooper717fb2c2010-12-08 08:44:59 -080097
Caspar Zhangff92e942012-02-29 10:58:15 +080098 read_cpuset_files(CPATH, "cpus", buf);
99 write_cpuset_files(CPATH_NEW, "cpus", buf);
100 read_cpuset_files(CPATH, "mems", mems);
101 write_cpuset_files(CPATH_NEW, "mems", mems);
Zhouping Liue0963392013-04-23 15:12:55 +0800102 SAFE_FILE_PRINTF(cleanup, CPATH_NEW "/tasks", "%d", getpid());
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800103
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800104 switch (child = fork()) {
Caspar Zhang05697c42012-02-20 19:20:57 +0800105 case -1:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800106 tst_brkm(TBROK | TERRNO, cleanup, "fork");
Caspar Zhang05697c42012-02-20 19:20:57 +0800107 case 0:
Lans Zhangcb2967b2013-04-17 16:35:27 +0800108 for (i = 0; i < nnodes; i++) {
109 if (nodes[i] >= MAXNODES)
110 continue;
111 set_node(nmask, nodes[i]);
112 }
113 if (set_mempolicy(MPOL_BIND, nmask, MAXNODES) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800114 tst_brkm(TBROK | TERRNO, cleanup, "set_mempolicy");
Caspar Zhangcd8fb152012-02-29 16:14:24 +0800115 exit(mem_hog_cpuset(ncpus > 1 ? ncpus : 1));
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800116 }
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800117 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800118 tst_count = 0;
Caspar Zhanga98ac192012-08-09 14:15:41 +0800119 snprintf(buf, BUFSIZ, "%d", nodes[0]);
Caspar Zhangff92e942012-02-29 10:58:15 +0800120 write_cpuset_files(CPATH_NEW, "mems", buf);
Caspar Zhanga98ac192012-08-09 14:15:41 +0800121 snprintf(buf, BUFSIZ, "%d", nodes[1]);
Caspar Zhangff92e942012-02-29 10:58:15 +0800122 write_cpuset_files(CPATH_NEW, "mems", buf);
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800123 }
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800124
125 if (waitpid(child, &status, WUNTRACED | WCONTINUED) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800126 tst_brkm(TBROK | TERRNO, cleanup, "waitpid");
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800127 if (WEXITSTATUS(status) != 0)
128 tst_resm(TFAIL, "child exit status is %d", WEXITSTATUS(status));
129}
130
131void setup(void)
132{
Garrett Cooper40495b82011-01-19 00:48:39 -0800133 tst_require_root(NULL);
134
Zhouping Liu263f6952012-02-27 16:02:53 +0800135 if (tst_kvercmp(2, 6, 32) < 0)
136 tst_brkm(TCONF, NULL, "2.6.32 or greater kernel required");
137
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800138 tst_sig(FORK, DEF_HANDLER, cleanup);
139 TEST_PAUSE;
Zhouping Liu8e6aafc2012-02-27 16:02:51 +0800140
141 mount_mem("cpuset", "cpuset", NULL, CPATH, CPATH_NEW);
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800142}
Zhouping Liu8e6aafc2012-02-27 16:02:51 +0800143
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800144void cleanup(void)
145{
Zhouping Liu8e6aafc2012-02-27 16:02:51 +0800146 umount_mem(CPATH, CPATH_NEW);
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800147}
148
Zhouping Liu8e6aafc2012-02-27 16:02:51 +0800149static void sighandler(int signo LTP_ATTRIBUTE_UNUSED)
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800150{
151 end = 1;
152}
153
Zhouping Liu8e6aafc2012-02-27 16:02:51 +0800154static int mem_hog(void)
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800155{
156 long pagesize;
157 unsigned long *addr;
158 int ret = 0;
159
160 pagesize = getpagesize();
161 while (!end) {
162 addr = mmap(NULL, pagesize * 10, PROT_READ | PROT_WRITE,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800163 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800164 if (addr == MAP_FAILED) {
165 ret = 1;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800166 tst_resm(TFAIL | TERRNO, "mmap");
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800167 break;
168 }
169 memset(addr, 0xF7, pagesize * 10);
170 munmap(addr, pagesize * 10);
171 }
172 return ret;
173}
174
Zhouping Liu8e6aafc2012-02-27 16:02:51 +0800175static int mem_hog_cpuset(int ntasks)
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800176{
Caspar Zhangc406ee42012-02-29 17:41:57 +0800177 int i, lc, status, ret = 0;
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800178 struct sigaction sa;
Caspar Zhangc406ee42012-02-29 17:41:57 +0800179 pid_t *pids;
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800180
181 if (ntasks <= 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800182 tst_brkm(TBROK | TERRNO, cleanup, "ntasks is small.");
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800183 sa.sa_handler = sighandler;
184 if (sigemptyset(&sa.sa_mask) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800185 tst_brkm(TBROK | TERRNO, cleanup, "sigemptyset");
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800186 sa.sa_flags = 0;
187 if (sigaction(SIGUSR1, &sa, NULL) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800188 tst_brkm(TBROK | TERRNO, cleanup, "sigaction");
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800189
Caspar Zhangc406ee42012-02-29 17:41:57 +0800190 pids = malloc(sizeof(pid_t) * ntasks);
191 if (pids == NULL)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800192 tst_brkm(TBROK | TERRNO, cleanup, "malloc");
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800193 for (i = 0; i < ntasks; i++) {
Caspar Zhangc406ee42012-02-29 17:41:57 +0800194 switch (pids[i] = fork()) {
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800195 case -1:
Wanlong Gao354ebb42012-12-07 10:10:04 +0800196 tst_resm(TFAIL | TERRNO, "fork %d", pids[i]);
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800197 ret = 1;
198 break;
199 case 0:
200 ret = mem_hog();
201 exit(ret);
202 default:
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800203 break;
204 }
205 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800206 for (lc = 0; TEST_LOOPING(lc); lc++) ;
Caspar Zhangc406ee42012-02-29 17:41:57 +0800207 while (i--) {
208 if (kill(pids[i], SIGUSR1) == -1) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800209 tst_resm(TFAIL | TERRNO, "kill %d", pids[i]);
Caspar Zhangc406ee42012-02-29 17:41:57 +0800210 ret = 1;
211 }
212 }
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800213 while (waitpid(-1, &status, WUNTRACED | WCONTINUED) > 0) {
Caspar Zhangcd8fb152012-02-29 16:14:24 +0800214 if (WIFEXITED(status)) {
Caspar Zhangeaa79782012-02-29 17:12:53 +0800215 if (WEXITSTATUS(status) != 0) {
Caspar Zhangcd8fb152012-02-29 16:14:24 +0800216 tst_resm(TFAIL, "child exit status is %d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800217 WEXITSTATUS(status));
Caspar Zhangeaa79782012-02-29 17:12:53 +0800218 ret = 1;
219 }
Caspar Zhangcd8fb152012-02-29 16:14:24 +0800220 } else if (WIFSIGNALED(status)) {
221 tst_resm(TFAIL, "child caught signal %d",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800222 WTERMSIG(status));
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800223 ret = 1;
224 }
225 }
226 return ret;
227}
228
Zhouping Liu8e6aafc2012-02-27 16:02:51 +0800229static long count_cpu(void)
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800230{
231 int ncpus = 0;
232
Caspar Zhang05697c42012-02-20 19:20:57 +0800233 while (path_exist(PATH_SYS_SYSTEM "/cpu/cpu%d", ncpus))
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800234 ncpus++;
235
236 return ncpus;
237}
238
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800239#else /* no NUMA */
Caspar Zhang05697c42012-02-20 19:20:57 +0800240int main(void)
241{
242 tst_brkm(TCONF, NULL, "no NUMA development packages installed.");
Garrett Cooper717fb2c2010-12-08 08:44:59 -0800243}
Garrett Cooper99854e02011-01-18 01:40:10 -0800244#endif