1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2011 Red Hat, Inc. 4 * Copyright (C) 2021 Xie Ziyao <xieziyao@huawei.com> 5 */ 6 7/*\ 8 * [Description] 9 * 10 * Test ru_maxrss behaviors in struct rusage. 11 * 12 * This test program is backported from upstream commit: 1f10206cf8e9, which 13 * fills ru_maxrss value in struct rusage according to rss hiwater mark. To 14 * make sure this feature works correctly, a series of tests are executed in 15 * this program. 16 */ 17 18#include <stdlib.h> 19#include <stdio.h> 20 21#include "tst_test.h" 22#include "getrusage03.h" 23 24#define TESTBIN "getrusage03_child" 25 26static struct rusage ru; 27static long maxrss_init; 28 29static const char *const resource[] = { 30 TESTBIN, 31 NULL, 32}; 33 34static void inherit_fork1(void) 35{ 36 SAFE_GETRUSAGE(RUSAGE_SELF, &ru); 37 maxrss_init = ru.ru_maxrss; 38 39 if (!SAFE_FORK()) { 40 SAFE_GETRUSAGE(RUSAGE_SELF, &ru); 41 42 if (is_in_delta(maxrss_init - ru.ru_maxrss)) 43 tst_res(TPASS, "initial.self ~= child.self"); 44 else 45 tst_res(TFAIL, "child.self = %li, expected %li", 46 ru.ru_maxrss, maxrss_init); 47 exit(0); 48 } 49 tst_reap_children(); 50} 51 52static void inherit_fork2(void) 53{ 54 SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru); 55 56 if (is_in_delta(ru.ru_maxrss - 102400)) 57 tst_res(TPASS, "initial.children ~= 100MB"); 58 else 59 tst_res(TFAIL, "initial.children = %li, expected %i", 60 ru.ru_maxrss, 102400); 61 62 if (!SAFE_FORK()) { 63 SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru); 64 65 if (!ru.ru_maxrss) 66 tst_res(TPASS, "child.children == 0"); 67 else 68 tst_res(TFAIL, "child.children = %li, expected %i", 69 ru.ru_maxrss, 0); 70 exit(0); 71 } 72 tst_reap_children(); 73} 74 75static void grandchild_maxrss(void) 76{ 77 if (!SAFE_FORK()) 78 SAFE_EXECLP("getrusage03_child", "getrusage03_child", 79 "grand_consume", "300", NULL); 80 tst_reap_children(); 81 SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru); 82 83 if (is_in_delta(ru.ru_maxrss - 307200)) 84 tst_res(TPASS, "child.children ~= 300MB"); 85 else 86 tst_res(TFAIL, "child.children = %li, expected %i", 87 ru.ru_maxrss, 307200); 88} 89 90static void zombie(void) 91{ 92 SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru); 93 maxrss_init = ru.ru_maxrss; 94 95 pid_t pid = SAFE_FORK(); 96 97 if (!pid) 98 SAFE_EXECLP("getrusage03_child", "getrusage03_child", 99 "consume", "400", NULL); 100 101 TST_PROCESS_STATE_WAIT(pid, 'Z', 0); 102 SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru); 103 if (is_in_delta(ru.ru_maxrss - maxrss_init)) 104 tst_res(TPASS, "initial.children ~= pre_wait.children"); 105 else 106 tst_res(TFAIL, "pre_wait.children = %li, expected %li", 107 ru.ru_maxrss, maxrss_init); 108 109 tst_reap_children(); 110 SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru); 111 if (is_in_delta(ru.ru_maxrss - 409600)) 112 tst_res(TPASS, "post_wait.children ~= 400MB"); 113 else 114 tst_res(TFAIL, "post_wait.children = %li, expected %i", 115 ru.ru_maxrss, 409600); 116} 117 118static void sig_ign(void) 119{ 120 SAFE_SIGNAL(SIGCHLD, SIG_IGN); 121 SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru); 122 maxrss_init = ru.ru_maxrss; 123 124 pid_t pid = SAFE_FORK(); 125 126 if (!pid) 127 SAFE_EXECLP("getrusage03_child", "getrusage03_child", 128 "consume", "500", NULL); 129 130 TST_PROCESS_EXIT_WAIT(pid, 0); 131 SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru); 132 if (is_in_delta(ru.ru_maxrss - maxrss_init)) 133 tst_res(TPASS, "initial.children ~= after_zombie.children"); 134 else 135 tst_res(TFAIL, "after_zombie.children = %li, expected %li", 136 ru.ru_maxrss, maxrss_init); 137 138 SAFE_SIGNAL(SIGCHLD, SIG_DFL); 139} 140 141static void inherit_exec(void) 142{ 143 if (!SAFE_FORK()) { 144 char str_maxrss_self[BUFSIZ], str_maxrss_child[BUFSIZ]; 145 146 SAFE_GETRUSAGE(RUSAGE_SELF, &ru); 147 sprintf(str_maxrss_self, "%ld", ru.ru_maxrss); 148 SAFE_GETRUSAGE(RUSAGE_CHILDREN, &ru); 149 sprintf(str_maxrss_child, "%ld", ru.ru_maxrss); 150 151 SAFE_EXECLP("getrusage03_child", "getrusage03_child", 152 "compare", str_maxrss_self, str_maxrss_child, NULL); 153 } 154 tst_reap_children(); 155} 156 157void (*testfunc_list[])(void) = { 158 inherit_fork1, inherit_fork2, grandchild_maxrss, 159 zombie, sig_ign, inherit_exec 160}; 161 162static void run(unsigned int i) 163{ 164 if (!SAFE_FORK()) { 165 if (!SAFE_FORK()) { 166 consume_mb(100); 167 exit(0); 168 } 169 170 SAFE_WAIT(NULL); 171 172 testfunc_list[i](); 173 } 174} 175 176static struct tst_test test = { 177 .forks_child = 1, 178 .child_needs_reinit = 1, 179 .resource_files = resource, 180 .min_mem_avail = 512, 181 .tags = (const struct tst_tag[]) { 182 {"linux-git", "1f10206cf8e9"}, 183 {} 184 }, 185 .test = run, 186 .tcnt = ARRAY_SIZE(testfunc_list), 187 .caps = (struct tst_cap []) { 188 TST_CAP(TST_CAP_REQ, CAP_IPC_LOCK), 189 {} 190 }, 191}; 192