1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (C) 2010-2017 Red Hat, Inc. 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 5f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 6f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 7f08c3bdfSopenharmony_ci * (at your option) any later version. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 10f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * Out Of Memory when changing cpuset's mems on NUMA. There was a 15f08c3bdfSopenharmony_ci * problem reported upstream that the allocator may see an empty 16f08c3bdfSopenharmony_ci * nodemask when changing cpuset's mems. 17f08c3bdfSopenharmony_ci * http://lkml.org/lkml/2010/5/4/77 18f08c3bdfSopenharmony_ci * http://lkml.org/lkml/2010/5/4/79 19f08c3bdfSopenharmony_ci * http://lkml.org/lkml/2010/5/4/80 20f08c3bdfSopenharmony_ci * This test is based on the reproducers for the above issue. 21f08c3bdfSopenharmony_ci */ 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_ci#include "config.h" 24f08c3bdfSopenharmony_ci#include <stdio.h> 25f08c3bdfSopenharmony_ci#include <sys/wait.h> 26f08c3bdfSopenharmony_ci#if HAVE_NUMA_H 27f08c3bdfSopenharmony_ci#include <numa.h> 28f08c3bdfSopenharmony_ci#endif 29f08c3bdfSopenharmony_ci#if HAVE_NUMAIF_H 30f08c3bdfSopenharmony_ci#include <numaif.h> 31f08c3bdfSopenharmony_ci#endif 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_ci#include "mem.h" 34f08c3bdfSopenharmony_ci#include "numa_helper.h" 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci#ifdef HAVE_NUMA_V2 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_civolatile int end; 39f08c3bdfSopenharmony_cistatic int *nodes; 40f08c3bdfSopenharmony_cistatic int nnodes; 41f08c3bdfSopenharmony_cistatic long ncpus; 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_cistatic void sighandler(int signo LTP_ATTRIBUTE_UNUSED); 44f08c3bdfSopenharmony_cistatic int mem_hog(void); 45f08c3bdfSopenharmony_cistatic int mem_hog_cpuset(int ntasks); 46f08c3bdfSopenharmony_cistatic long count_cpu(void); 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_cistatic void test_cpuset(void) 49f08c3bdfSopenharmony_ci{ 50f08c3bdfSopenharmony_ci int child, i; 51f08c3bdfSopenharmony_ci unsigned long nmask[MAXNODES / BITS_PER_LONG] = { 0 }; 52f08c3bdfSopenharmony_ci char buf[BUFSIZ]; 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_ci SAFE_CG_READ(tst_cg, "cpuset.cpus", buf, sizeof(buf)); 55f08c3bdfSopenharmony_ci SAFE_CG_PRINT(tst_cg, "cpuset.cpus", buf); 56f08c3bdfSopenharmony_ci SAFE_CG_READ(tst_cg, "cpuset.mems", buf, sizeof(buf)); 57f08c3bdfSopenharmony_ci SAFE_CG_PRINT(tst_cg, "cpuset.mems", buf); 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci child = SAFE_FORK(); 60f08c3bdfSopenharmony_ci if (child == 0) { 61f08c3bdfSopenharmony_ci for (i = 0; i < nnodes; i++) { 62f08c3bdfSopenharmony_ci if (nodes[i] >= MAXNODES) 63f08c3bdfSopenharmony_ci continue; 64f08c3bdfSopenharmony_ci set_node(nmask, nodes[i]); 65f08c3bdfSopenharmony_ci } 66f08c3bdfSopenharmony_ci if (set_mempolicy(MPOL_BIND, nmask, MAXNODES) == -1) 67f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "set_mempolicy"); 68f08c3bdfSopenharmony_ci exit(mem_hog_cpuset(ncpus > 1 ? ncpus : 1)); 69f08c3bdfSopenharmony_ci } 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci SAFE_CG_PRINTF(tst_cg, "cpuset.mems", "%d", nodes[0]); 72f08c3bdfSopenharmony_ci SAFE_CG_PRINTF(tst_cg, "cpuset.mems", "%d", nodes[1]); 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_ci tst_reap_children(); 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci tst_res(TPASS, "cpuset test pass"); 77f08c3bdfSopenharmony_ci} 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_cistatic void setup(void) 80f08c3bdfSopenharmony_ci{ 81f08c3bdfSopenharmony_ci ncpus = count_cpu(); 82f08c3bdfSopenharmony_ci if (get_allowed_nodes_arr(NH_MEMS | NH_CPUS, &nnodes, &nodes) < 0) 83f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "get_allowed_nodes_arr"); 84f08c3bdfSopenharmony_ci if (nnodes <= 1) 85f08c3bdfSopenharmony_ci tst_brk(TCONF, "requires a NUMA system."); 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci SAFE_CG_PRINTF(tst_cg, "cgroup.procs", "%d", getpid()); 88f08c3bdfSopenharmony_ci} 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_cistatic void sighandler(int signo LTP_ATTRIBUTE_UNUSED) 91f08c3bdfSopenharmony_ci{ 92f08c3bdfSopenharmony_ci end = 1; 93f08c3bdfSopenharmony_ci} 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_cistatic int mem_hog(void) 96f08c3bdfSopenharmony_ci{ 97f08c3bdfSopenharmony_ci long pagesize; 98f08c3bdfSopenharmony_ci unsigned long *addr; 99f08c3bdfSopenharmony_ci int ret = 0; 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci pagesize = getpagesize(); 102f08c3bdfSopenharmony_ci while (!end) { 103f08c3bdfSopenharmony_ci addr = SAFE_MMAP(NULL, pagesize * 10, PROT_READ | PROT_WRITE, 104f08c3bdfSopenharmony_ci MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 105f08c3bdfSopenharmony_ci memset(addr, 0xF7, pagesize * 10); 106f08c3bdfSopenharmony_ci SAFE_MUNMAP(addr, pagesize * 10); 107f08c3bdfSopenharmony_ci } 108f08c3bdfSopenharmony_ci return ret; 109f08c3bdfSopenharmony_ci} 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_cistatic int mem_hog_cpuset(int ntasks) 112f08c3bdfSopenharmony_ci{ 113f08c3bdfSopenharmony_ci int i, status, ret = 0; 114f08c3bdfSopenharmony_ci struct sigaction sa; 115f08c3bdfSopenharmony_ci pid_t *pids; 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci if (ntasks <= 0) 118f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "ntasks is small."); 119f08c3bdfSopenharmony_ci sa.sa_handler = sighandler; 120f08c3bdfSopenharmony_ci if (sigemptyset(&sa.sa_mask) < 0) 121f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sigemptyset"); 122f08c3bdfSopenharmony_ci sa.sa_flags = 0; 123f08c3bdfSopenharmony_ci if (sigaction(SIGUSR1, &sa, NULL) < 0) 124f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sigaction"); 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_ci pids = SAFE_MALLOC(sizeof(pid_t) * ntasks); 127f08c3bdfSopenharmony_ci for (i = 0; i < ntasks; i++) { 128f08c3bdfSopenharmony_ci switch (pids[i] = fork()) { 129f08c3bdfSopenharmony_ci case -1: 130f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "fork %d", pids[i]); 131f08c3bdfSopenharmony_ci ret = 1; 132f08c3bdfSopenharmony_ci break; 133f08c3bdfSopenharmony_ci case 0: 134f08c3bdfSopenharmony_ci ret = mem_hog(); 135f08c3bdfSopenharmony_ci exit(ret); 136f08c3bdfSopenharmony_ci default: 137f08c3bdfSopenharmony_ci break; 138f08c3bdfSopenharmony_ci } 139f08c3bdfSopenharmony_ci } 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci while (i--) { 142f08c3bdfSopenharmony_ci if (kill(pids[i], SIGUSR1) == -1) { 143f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "kill %d", pids[i]); 144f08c3bdfSopenharmony_ci ret = 1; 145f08c3bdfSopenharmony_ci } 146f08c3bdfSopenharmony_ci } 147f08c3bdfSopenharmony_ci while (waitpid(-1, &status, WUNTRACED | WCONTINUED) > 0) { 148f08c3bdfSopenharmony_ci if (WIFEXITED(status)) { 149f08c3bdfSopenharmony_ci if (WEXITSTATUS(status) != 0) { 150f08c3bdfSopenharmony_ci tst_res(TFAIL, "child exit status is %d", 151f08c3bdfSopenharmony_ci WEXITSTATUS(status)); 152f08c3bdfSopenharmony_ci ret = 1; 153f08c3bdfSopenharmony_ci } 154f08c3bdfSopenharmony_ci } else if (WIFSIGNALED(status)) { 155f08c3bdfSopenharmony_ci tst_res(TFAIL, "child caught signal %d", 156f08c3bdfSopenharmony_ci WTERMSIG(status)); 157f08c3bdfSopenharmony_ci ret = 1; 158f08c3bdfSopenharmony_ci } 159f08c3bdfSopenharmony_ci } 160f08c3bdfSopenharmony_ci return ret; 161f08c3bdfSopenharmony_ci} 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_cistatic long count_cpu(void) 164f08c3bdfSopenharmony_ci{ 165f08c3bdfSopenharmony_ci int ncpus = 0; 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_ci while (path_exist(PATH_SYS_SYSTEM "/cpu/cpu%d", ncpus)) 168f08c3bdfSopenharmony_ci ncpus++; 169f08c3bdfSopenharmony_ci 170f08c3bdfSopenharmony_ci return ncpus; 171f08c3bdfSopenharmony_ci} 172f08c3bdfSopenharmony_ci 173f08c3bdfSopenharmony_cistatic struct tst_test test = { 174f08c3bdfSopenharmony_ci .needs_root = 1, 175f08c3bdfSopenharmony_ci .forks_child = 1, 176f08c3bdfSopenharmony_ci .setup = setup, 177f08c3bdfSopenharmony_ci .test_all = test_cpuset, 178f08c3bdfSopenharmony_ci .needs_cgroup_ctrls = (const char *const []){ "cpuset", NULL }, 179f08c3bdfSopenharmony_ci}; 180f08c3bdfSopenharmony_ci 181f08c3bdfSopenharmony_ci#else 182f08c3bdfSopenharmony_ci TST_TEST_TCONF(NUMA_ERROR_MSG); 183f08c3bdfSopenharmony_ci#endif 184