1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (C) 2012-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 * Description: 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * The case is designed to test min_free_kbytes tunable. 17f08c3bdfSopenharmony_ci * 18f08c3bdfSopenharmony_ci * The tune is used to control free memory, and system always 19f08c3bdfSopenharmony_ci * reserve min_free_kbytes memory at least. 20f08c3bdfSopenharmony_ci * 21f08c3bdfSopenharmony_ci * Since the tune is not too large or too little, which will 22f08c3bdfSopenharmony_ci * lead to the system hang, so I choose two cases, and test them 23f08c3bdfSopenharmony_ci * on all overcommit_memory policy, at the same time, compare 24f08c3bdfSopenharmony_ci * the current free memory with the tunable value repeatedly. 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci * a) default min_free_kbytes with all overcommit memory policy 27f08c3bdfSopenharmony_ci * b) 2x default value with all overcommit memory policy 28f08c3bdfSopenharmony_ci * c) 5% of MemFree or %2 MemTotal with all overcommit memory policy 29f08c3bdfSopenharmony_ci */ 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci#include <sys/wait.h> 32f08c3bdfSopenharmony_ci#include <errno.h> 33f08c3bdfSopenharmony_ci#include <fcntl.h> 34f08c3bdfSopenharmony_ci#include <signal.h> 35f08c3bdfSopenharmony_ci#include <stdio.h> 36f08c3bdfSopenharmony_ci#include <stdlib.h> 37f08c3bdfSopenharmony_ci#include "lapi/abisize.h" 38f08c3bdfSopenharmony_ci#include "mem.h" 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_ci#define MAP_SIZE (1UL<<20) 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_civolatile int end; 43f08c3bdfSopenharmony_cistatic long default_tune = -1; 44f08c3bdfSopenharmony_cistatic unsigned long total_mem; 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_cistatic void test_tune(unsigned long overcommit_policy); 47f08c3bdfSopenharmony_cistatic int eatup_mem(unsigned long overcommit_policy); 48f08c3bdfSopenharmony_cistatic void check_monitor(void); 49f08c3bdfSopenharmony_cistatic void sighandler(int signo LTP_ATTRIBUTE_UNUSED); 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_cistatic void min_free_kbytes_test(void) 52f08c3bdfSopenharmony_ci{ 53f08c3bdfSopenharmony_ci int pid, status; 54f08c3bdfSopenharmony_ci struct sigaction sa; 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci sa.sa_handler = sighandler; 57f08c3bdfSopenharmony_ci if (sigemptyset(&sa.sa_mask) < 0) 58f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sigemptyset"); 59f08c3bdfSopenharmony_ci sa.sa_flags = 0; 60f08c3bdfSopenharmony_ci if (sigaction(SIGUSR1, &sa, NULL) < 0) 61f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sigaction"); 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci pid = SAFE_FORK(); 64f08c3bdfSopenharmony_ci if (pid == 0) { 65f08c3bdfSopenharmony_ci /* startup the check monitor */ 66f08c3bdfSopenharmony_ci check_monitor(); 67f08c3bdfSopenharmony_ci exit(0); 68f08c3bdfSopenharmony_ci } 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_ci test_tune(2); 71f08c3bdfSopenharmony_ci test_tune(0); 72f08c3bdfSopenharmony_ci test_tune(1); 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_ci SAFE_KILL(pid, SIGUSR1); 75f08c3bdfSopenharmony_ci SAFE_WAITPID(pid, &status, WUNTRACED | WCONTINUED); 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci if (WIFEXITED(status) && WEXITSTATUS(status) != 0) 78f08c3bdfSopenharmony_ci tst_res(TFAIL, 79f08c3bdfSopenharmony_ci "check_monitor child exit with status: %d", status); 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci tst_res(TPASS, "min_free_kbytes test pass"); 82f08c3bdfSopenharmony_ci} 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_cistatic void test_tune(unsigned long overcommit_policy) 85f08c3bdfSopenharmony_ci{ 86f08c3bdfSopenharmony_ci int status; 87f08c3bdfSopenharmony_ci int pid[3]; 88f08c3bdfSopenharmony_ci int ret, i; 89f08c3bdfSopenharmony_ci unsigned long tune, memfree, memtotal; 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci set_sys_tune("overcommit_memory", overcommit_policy, 1); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci for (i = 0; i < 3; i++) { 94f08c3bdfSopenharmony_ci /* case1 */ 95f08c3bdfSopenharmony_ci if (i == 0) 96f08c3bdfSopenharmony_ci set_sys_tune("min_free_kbytes", default_tune, 1); 97f08c3bdfSopenharmony_ci /* case2 */ 98f08c3bdfSopenharmony_ci else if (i == 1) { 99f08c3bdfSopenharmony_ci set_sys_tune("min_free_kbytes", 2 * default_tune, 1); 100f08c3bdfSopenharmony_ci /* case3 */ 101f08c3bdfSopenharmony_ci } else { 102f08c3bdfSopenharmony_ci memfree = SAFE_READ_MEMINFO("MemFree:"); 103f08c3bdfSopenharmony_ci memtotal = SAFE_READ_MEMINFO("MemTotal:"); 104f08c3bdfSopenharmony_ci tune = memfree / 20; 105f08c3bdfSopenharmony_ci if (tune > (memtotal / 50)) 106f08c3bdfSopenharmony_ci tune = memtotal / 50; 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci set_sys_tune("min_free_kbytes", tune, 1); 109f08c3bdfSopenharmony_ci } 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci fflush(stdout); 112f08c3bdfSopenharmony_ci switch (pid[i] = fork()) { 113f08c3bdfSopenharmony_ci case -1: 114f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "fork"); 115f08c3bdfSopenharmony_ci case 0: 116f08c3bdfSopenharmony_ci ret = eatup_mem(overcommit_policy); 117f08c3bdfSopenharmony_ci exit(ret); 118f08c3bdfSopenharmony_ci } 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_ci SAFE_WAITPID(pid[i], &status, WUNTRACED | WCONTINUED); 121f08c3bdfSopenharmony_ci 122f08c3bdfSopenharmony_ci if (overcommit_policy == 2) { 123f08c3bdfSopenharmony_ci if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 124f08c3bdfSopenharmony_ci tst_res(TFAIL, 125f08c3bdfSopenharmony_ci "child unexpectedly failed: %d", 126f08c3bdfSopenharmony_ci status); 127f08c3bdfSopenharmony_ci } else if (overcommit_policy == 1) { 128f08c3bdfSopenharmony_ci if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGKILL) 129f08c3bdfSopenharmony_ci#ifdef TST_ABI32 130f08c3bdfSopenharmony_ci { 131f08c3bdfSopenharmony_ci if (total_mem < 3145728UL) 132f08c3bdfSopenharmony_ci#endif 133f08c3bdfSopenharmony_ci tst_res(TFAIL, 134f08c3bdfSopenharmony_ci "child unexpectedly failed: %d", 135f08c3bdfSopenharmony_ci status); 136f08c3bdfSopenharmony_ci#ifdef TST_ABI32 137f08c3bdfSopenharmony_ci /* in 32-bit system, a process allocate about 3Gb memory at most */ 138f08c3bdfSopenharmony_ci else 139f08c3bdfSopenharmony_ci tst_res(TINFO, "Child can't allocate " 140f08c3bdfSopenharmony_ci ">3Gb memory in 32bit system"); 141f08c3bdfSopenharmony_ci } 142f08c3bdfSopenharmony_ci#endif 143f08c3bdfSopenharmony_ci } else { 144f08c3bdfSopenharmony_ci if (WIFEXITED(status)) { 145f08c3bdfSopenharmony_ci if (WEXITSTATUS(status) != 0) { 146f08c3bdfSopenharmony_ci tst_res(TFAIL, "child unexpectedly " 147f08c3bdfSopenharmony_ci "failed: %d", status); 148f08c3bdfSopenharmony_ci } 149f08c3bdfSopenharmony_ci } else if (!WIFSIGNALED(status) || 150f08c3bdfSopenharmony_ci WTERMSIG(status) != SIGKILL) { 151f08c3bdfSopenharmony_ci tst_res(TFAIL, 152f08c3bdfSopenharmony_ci "child unexpectedly failed: %d", 153f08c3bdfSopenharmony_ci status); 154f08c3bdfSopenharmony_ci } 155f08c3bdfSopenharmony_ci } 156f08c3bdfSopenharmony_ci } 157f08c3bdfSopenharmony_ci} 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_cistatic int eatup_mem(unsigned long overcommit_policy) 160f08c3bdfSopenharmony_ci{ 161f08c3bdfSopenharmony_ci int ret = 0; 162f08c3bdfSopenharmony_ci unsigned long memfree; 163f08c3bdfSopenharmony_ci void *addrs; 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci memfree = SAFE_READ_MEMINFO("MemFree:"); 166f08c3bdfSopenharmony_ci printf("memfree is %lu kB before eatup mem\n", memfree); 167f08c3bdfSopenharmony_ci while (1) { 168f08c3bdfSopenharmony_ci addrs = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, 169f08c3bdfSopenharmony_ci MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 170f08c3bdfSopenharmony_ci if (addrs == MAP_FAILED) { 171f08c3bdfSopenharmony_ci if (overcommit_policy != 1 && errno != ENOMEM) { 172f08c3bdfSopenharmony_ci perror("mmap"); 173f08c3bdfSopenharmony_ci ret = -1; 174f08c3bdfSopenharmony_ci } 175f08c3bdfSopenharmony_ci break; 176f08c3bdfSopenharmony_ci } 177f08c3bdfSopenharmony_ci memset(addrs, 1, MAP_SIZE); 178f08c3bdfSopenharmony_ci } 179f08c3bdfSopenharmony_ci memfree = SAFE_READ_MEMINFO("MemFree:"); 180f08c3bdfSopenharmony_ci printf("memfree is %lu kB after eatup mem\n", memfree); 181f08c3bdfSopenharmony_ci 182f08c3bdfSopenharmony_ci return ret; 183f08c3bdfSopenharmony_ci} 184f08c3bdfSopenharmony_ci 185f08c3bdfSopenharmony_cistatic void check_monitor(void) 186f08c3bdfSopenharmony_ci{ 187f08c3bdfSopenharmony_ci unsigned long tune; 188f08c3bdfSopenharmony_ci unsigned long memfree; 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_ci while (end) { 191f08c3bdfSopenharmony_ci memfree = SAFE_READ_MEMINFO("MemFree:"); 192f08c3bdfSopenharmony_ci tune = get_sys_tune("min_free_kbytes"); 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci if (memfree < tune) { 195f08c3bdfSopenharmony_ci tst_res(TINFO, "MemFree is %lu kB, " 196f08c3bdfSopenharmony_ci "min_free_kbytes is %lu kB", memfree, tune); 197f08c3bdfSopenharmony_ci tst_res(TFAIL, "MemFree < min_free_kbytes"); 198f08c3bdfSopenharmony_ci } 199f08c3bdfSopenharmony_ci 200f08c3bdfSopenharmony_ci sleep(2); 201f08c3bdfSopenharmony_ci } 202f08c3bdfSopenharmony_ci} 203f08c3bdfSopenharmony_ci 204f08c3bdfSopenharmony_cistatic void sighandler(int signo LTP_ATTRIBUTE_UNUSED) 205f08c3bdfSopenharmony_ci{ 206f08c3bdfSopenharmony_ci end = 1; 207f08c3bdfSopenharmony_ci} 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_cistatic void setup(void) 210f08c3bdfSopenharmony_ci{ 211f08c3bdfSopenharmony_ci if (get_sys_tune("panic_on_oom")) { 212f08c3bdfSopenharmony_ci tst_brk(TCONF, 213f08c3bdfSopenharmony_ci "panic_on_oom is set, disable it to run these testcases"); 214f08c3bdfSopenharmony_ci } 215f08c3bdfSopenharmony_ci 216f08c3bdfSopenharmony_ci total_mem = SAFE_READ_MEMINFO("MemTotal:") + SAFE_READ_MEMINFO("SwapTotal:"); 217f08c3bdfSopenharmony_ci 218f08c3bdfSopenharmony_ci default_tune = get_sys_tune("min_free_kbytes"); 219f08c3bdfSopenharmony_ci} 220f08c3bdfSopenharmony_ci 221f08c3bdfSopenharmony_cistatic struct tst_test test = { 222f08c3bdfSopenharmony_ci .needs_root = 1, 223f08c3bdfSopenharmony_ci .forks_child = 1, 224f08c3bdfSopenharmony_ci .max_runtime = TST_UNLIMITED_RUNTIME, 225f08c3bdfSopenharmony_ci .setup = setup, 226f08c3bdfSopenharmony_ci .test_all = min_free_kbytes_test, 227f08c3bdfSopenharmony_ci .save_restore = (const struct tst_path_val[]) { 228f08c3bdfSopenharmony_ci {"/proc/sys/vm/overcommit_memory", NULL, TST_SR_TBROK}, 229f08c3bdfSopenharmony_ci {"/proc/sys/vm/min_free_kbytes", NULL, TST_SR_TBROK}, 230f08c3bdfSopenharmony_ci {} 231f08c3bdfSopenharmony_ci }, 232f08c3bdfSopenharmony_ci}; 233