1 /* 2 * Out Of Memory (OOM) for CPUSET 3 * 4 * The program is designed to cope with unpredictable like amount and 5 * system physical memory, swap size and other VMM technology like KSM, 6 * memcg, memory hotplug and so on which may affect the OOM 7 * behaviours. It simply increase the memory consumption 3G each time 8 * until all the available memory is consumed and OOM is triggered. 9 * 10 * Copyright (C) 2010-2017 Red Hat, Inc. 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 20 * the GNU General Public License for more details. 21 */ 22 23 #include "config.h" 24 #include <sys/types.h> 25 #include <sys/stat.h> 26 #include <errno.h> 27 #include <fcntl.h> 28 #include <stdio.h> 29 #if HAVE_NUMA_H 30 #include <numa.h> 31 #endif 32 33 #include "numa_helper.h" 34 #include "mem.h" 35 36 #ifdef HAVE_NUMA_V2 37 38 static int cpuset_mounted; 39 40 static void verify_oom(void) 41 { 42 #if __WORDSIZE == 32 43 tst_brk(TCONF, "test is not designed for 32-bit system."); 44 #endif 45 46 tst_res(TINFO, "OOM on CPUSET..."); 47 testoom(0, 0, ENOMEM, 1); 48 49 if (is_numa(NULL, NH_MEMS, 2)) { 50 /* 51 * Under NUMA system, the migration of cpuset's memory 52 * is in charge of cpuset.memory_migrate, we can write 53 * 1 to cpuset.memory_migrate to enable the migration. 54 */ 55 write_cpuset_files(CPATH_NEW, "memory_migrate", "1"); 56 tst_res(TINFO, "OOM on CPUSET with mem migrate:"); 57 testoom(0, 0, ENOMEM, 1); 58 } 59 } 60 61 static void setup(void) 62 { 63 int memnode, ret; 64 65 if (!is_numa(NULL, NH_MEMS, 1)) 66 tst_brk(TCONF, "requires NUMA with at least 1 node"); 67 68 overcommit = get_sys_tune("overcommit_memory"); 69 set_sys_tune("overcommit_memory", 1, 1); 70 71 mount_mem("cpuset", "cpuset", NULL, CPATH, CPATH_NEW); 72 cpuset_mounted = 1; 73 74 /* 75 * Some nodes do not contain memory, so use 76 * get_allowed_nodes(NH_MEMS) to get a memory 77 * node. This operation also applies to Non-NUMA 78 * systems. 79 */ 80 ret = get_allowed_nodes(NH_MEMS, 1, &memnode); 81 if (ret < 0) 82 tst_brk(TBROK, "Failed to get a memory node " 83 "using get_allowed_nodes()"); 84 write_cpusets(memnode); 85 } 86 87 static void cleanup(void) 88 { 89 if (overcommit != -1) 90 set_sys_tune("overcommit_memory", overcommit, 0); 91 if (cpuset_mounted) 92 umount_mem(CPATH, CPATH_NEW); 93 } 94 95 static struct tst_test test = { 96 .needs_root = 1, 97 .forks_child = 1, 98 .timeout = -1, 99 .setup = setup, 100 .cleanup = cleanup, 101 .test_all = verify_oom, 102 }; 103 104 #else 105 TST_TEST_TCONF(NUMA_ERROR_MSG); 106 #endif 107