test_kmem.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #include <linux/limits.h>
  4. #include <fcntl.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/stat.h>
  9. #include <sys/types.h>
  10. #include <unistd.h>
  11. #include <sys/wait.h>
  12. #include <errno.h>
  13. #include <sys/sysinfo.h>
  14. #include <pthread.h>
  15. #include "../kselftest.h"
  16. #include "cgroup_util.h"
  17. /*
  18. * Memory cgroup charging is performed using percpu batches 64 pages
  19. * big (look at MEMCG_CHARGE_BATCH), whereas memory.stat is exact. So
  20. * the maximum discrepancy between charge and vmstat entries is number
  21. * of cpus multiplied by 64 pages.
  22. */
  23. #define MAX_VMSTAT_ERROR (4096 * 64 * get_nprocs())
  24. static int alloc_dcache(const char *cgroup, void *arg)
  25. {
  26. unsigned long i;
  27. struct stat st;
  28. char buf[128];
  29. for (i = 0; i < (unsigned long)arg; i++) {
  30. snprintf(buf, sizeof(buf),
  31. "/something-non-existent-with-a-long-name-%64lu-%d",
  32. i, getpid());
  33. stat(buf, &st);
  34. }
  35. return 0;
  36. }
  37. /*
  38. * This test allocates 100000 of negative dentries with long names.
  39. * Then it checks that "slab" in memory.stat is larger than 1M.
  40. * Then it sets memory.high to 1M and checks that at least 1/2
  41. * of slab memory has been reclaimed.
  42. */
  43. static int test_kmem_basic(const char *root)
  44. {
  45. int ret = KSFT_FAIL;
  46. char *cg = NULL;
  47. long slab0, slab1, current;
  48. cg = cg_name(root, "kmem_basic_test");
  49. if (!cg)
  50. goto cleanup;
  51. if (cg_create(cg))
  52. goto cleanup;
  53. if (cg_run(cg, alloc_dcache, (void *)100000))
  54. goto cleanup;
  55. slab0 = cg_read_key_long(cg, "memory.stat", "slab ");
  56. if (slab0 < (1 << 20))
  57. goto cleanup;
  58. cg_write(cg, "memory.high", "1M");
  59. /* wait for RCU freeing */
  60. sleep(1);
  61. slab1 = cg_read_key_long(cg, "memory.stat", "slab ");
  62. if (slab1 < 0)
  63. goto cleanup;
  64. current = cg_read_long(cg, "memory.current");
  65. if (current < 0)
  66. goto cleanup;
  67. if (slab1 < slab0 / 2 && current < slab0 / 2)
  68. ret = KSFT_PASS;
  69. cleanup:
  70. cg_destroy(cg);
  71. free(cg);
  72. return ret;
  73. }
  74. static void *alloc_kmem_fn(void *arg)
  75. {
  76. alloc_dcache(NULL, (void *)100);
  77. return NULL;
  78. }
  79. static int alloc_kmem_smp(const char *cgroup, void *arg)
  80. {
  81. int nr_threads = 2 * get_nprocs();
  82. pthread_t *tinfo;
  83. unsigned long i;
  84. int ret = -1;
  85. tinfo = calloc(nr_threads, sizeof(pthread_t));
  86. if (tinfo == NULL)
  87. return -1;
  88. for (i = 0; i < nr_threads; i++) {
  89. if (pthread_create(&tinfo[i], NULL, &alloc_kmem_fn,
  90. (void *)i)) {
  91. free(tinfo);
  92. return -1;
  93. }
  94. }
  95. for (i = 0; i < nr_threads; i++) {
  96. ret = pthread_join(tinfo[i], NULL);
  97. if (ret)
  98. break;
  99. }
  100. free(tinfo);
  101. return ret;
  102. }
  103. static int cg_run_in_subcgroups(const char *parent,
  104. int (*fn)(const char *cgroup, void *arg),
  105. void *arg, int times)
  106. {
  107. char *child;
  108. int i;
  109. for (i = 0; i < times; i++) {
  110. child = cg_name_indexed(parent, "child", i);
  111. if (!child)
  112. return -1;
  113. if (cg_create(child)) {
  114. cg_destroy(child);
  115. free(child);
  116. return -1;
  117. }
  118. if (cg_run(child, fn, NULL)) {
  119. cg_destroy(child);
  120. free(child);
  121. return -1;
  122. }
  123. cg_destroy(child);
  124. free(child);
  125. }
  126. return 0;
  127. }
  128. /*
  129. * The test creates and destroys a large number of cgroups. In each cgroup it
  130. * allocates some slab memory (mostly negative dentries) using 2 * NR_CPUS
  131. * threads. Then it checks the sanity of numbers on the parent level:
  132. * the total size of the cgroups should be roughly equal to
  133. * anon + file + kernel + sock.
  134. */
  135. static int test_kmem_memcg_deletion(const char *root)
  136. {
  137. long current, anon, file, kernel, sock, sum;
  138. int ret = KSFT_FAIL;
  139. char *parent;
  140. parent = cg_name(root, "kmem_memcg_deletion_test");
  141. if (!parent)
  142. goto cleanup;
  143. if (cg_create(parent))
  144. goto cleanup;
  145. if (cg_write(parent, "cgroup.subtree_control", "+memory"))
  146. goto cleanup;
  147. if (cg_run_in_subcgroups(parent, alloc_kmem_smp, NULL, 100))
  148. goto cleanup;
  149. current = cg_read_long(parent, "memory.current");
  150. anon = cg_read_key_long(parent, "memory.stat", "anon ");
  151. file = cg_read_key_long(parent, "memory.stat", "file ");
  152. kernel = cg_read_key_long(parent, "memory.stat", "kernel ");
  153. sock = cg_read_key_long(parent, "memory.stat", "sock ");
  154. if (current < 0 || anon < 0 || file < 0 || kernel < 0 || sock < 0)
  155. goto cleanup;
  156. sum = anon + file + kernel + sock;
  157. if (labs(sum - current) < MAX_VMSTAT_ERROR) {
  158. ret = KSFT_PASS;
  159. } else {
  160. printf("memory.current = %ld\n", current);
  161. printf("anon + file + kernel + sock = %ld\n", sum);
  162. printf("anon = %ld\n", anon);
  163. printf("file = %ld\n", file);
  164. printf("kernel = %ld\n", kernel);
  165. printf("sock = %ld\n", sock);
  166. }
  167. cleanup:
  168. cg_destroy(parent);
  169. free(parent);
  170. return ret;
  171. }
  172. /*
  173. * The test reads the entire /proc/kpagecgroup. If the operation went
  174. * successfully (and the kernel didn't panic), the test is treated as passed.
  175. */
  176. static int test_kmem_proc_kpagecgroup(const char *root)
  177. {
  178. unsigned long buf[128];
  179. int ret = KSFT_FAIL;
  180. ssize_t len;
  181. int fd;
  182. fd = open("/proc/kpagecgroup", O_RDONLY);
  183. if (fd < 0)
  184. return ret;
  185. do {
  186. len = read(fd, buf, sizeof(buf));
  187. } while (len > 0);
  188. if (len == 0)
  189. ret = KSFT_PASS;
  190. close(fd);
  191. return ret;
  192. }
  193. static void *pthread_wait_fn(void *arg)
  194. {
  195. sleep(100);
  196. return NULL;
  197. }
  198. static int spawn_1000_threads(const char *cgroup, void *arg)
  199. {
  200. int nr_threads = 1000;
  201. pthread_t *tinfo;
  202. unsigned long i;
  203. long stack;
  204. int ret = -1;
  205. tinfo = calloc(nr_threads, sizeof(pthread_t));
  206. if (tinfo == NULL)
  207. return -1;
  208. for (i = 0; i < nr_threads; i++) {
  209. if (pthread_create(&tinfo[i], NULL, &pthread_wait_fn,
  210. (void *)i)) {
  211. free(tinfo);
  212. return(-1);
  213. }
  214. }
  215. stack = cg_read_key_long(cgroup, "memory.stat", "kernel_stack ");
  216. if (stack >= 4096 * 1000)
  217. ret = 0;
  218. free(tinfo);
  219. return ret;
  220. }
  221. /*
  222. * The test spawns a process, which spawns 1000 threads. Then it checks
  223. * that memory.stat's kernel_stack is at least 1000 pages large.
  224. */
  225. static int test_kmem_kernel_stacks(const char *root)
  226. {
  227. int ret = KSFT_FAIL;
  228. char *cg = NULL;
  229. cg = cg_name(root, "kmem_kernel_stacks_test");
  230. if (!cg)
  231. goto cleanup;
  232. if (cg_create(cg))
  233. goto cleanup;
  234. if (cg_run(cg, spawn_1000_threads, NULL))
  235. goto cleanup;
  236. ret = KSFT_PASS;
  237. cleanup:
  238. cg_destroy(cg);
  239. free(cg);
  240. return ret;
  241. }
  242. /*
  243. * This test sequentionally creates 30 child cgroups, allocates some
  244. * kernel memory in each of them, and deletes them. Then it checks
  245. * that the number of dying cgroups on the parent level is 0.
  246. */
  247. static int test_kmem_dead_cgroups(const char *root)
  248. {
  249. int ret = KSFT_FAIL;
  250. char *parent;
  251. long dead;
  252. int i;
  253. parent = cg_name(root, "kmem_dead_cgroups_test");
  254. if (!parent)
  255. goto cleanup;
  256. if (cg_create(parent))
  257. goto cleanup;
  258. if (cg_write(parent, "cgroup.subtree_control", "+memory"))
  259. goto cleanup;
  260. if (cg_run_in_subcgroups(parent, alloc_dcache, (void *)100, 30))
  261. goto cleanup;
  262. for (i = 0; i < 5; i++) {
  263. dead = cg_read_key_long(parent, "cgroup.stat",
  264. "nr_dying_descendants ");
  265. if (dead == 0) {
  266. ret = KSFT_PASS;
  267. break;
  268. }
  269. /*
  270. * Reclaiming cgroups might take some time,
  271. * let's wait a bit and repeat.
  272. */
  273. sleep(1);
  274. }
  275. cleanup:
  276. cg_destroy(parent);
  277. free(parent);
  278. return ret;
  279. }
  280. /*
  281. * This test creates a sub-tree with 1000 memory cgroups.
  282. * Then it checks that the memory.current on the parent level
  283. * is greater than 0 and approximates matches the percpu value
  284. * from memory.stat.
  285. */
  286. static int test_percpu_basic(const char *root)
  287. {
  288. int ret = KSFT_FAIL;
  289. char *parent, *child;
  290. long current, percpu;
  291. int i;
  292. parent = cg_name(root, "percpu_basic_test");
  293. if (!parent)
  294. goto cleanup;
  295. if (cg_create(parent))
  296. goto cleanup;
  297. if (cg_write(parent, "cgroup.subtree_control", "+memory"))
  298. goto cleanup;
  299. for (i = 0; i < 1000; i++) {
  300. child = cg_name_indexed(parent, "child", i);
  301. if (!child)
  302. return -1;
  303. if (cg_create(child))
  304. goto cleanup_children;
  305. free(child);
  306. }
  307. current = cg_read_long(parent, "memory.current");
  308. percpu = cg_read_key_long(parent, "memory.stat", "percpu ");
  309. if (current > 0 && percpu > 0 && labs(current - percpu) <
  310. MAX_VMSTAT_ERROR)
  311. ret = KSFT_PASS;
  312. else
  313. printf("memory.current %ld\npercpu %ld\n",
  314. current, percpu);
  315. cleanup_children:
  316. for (i = 0; i < 1000; i++) {
  317. child = cg_name_indexed(parent, "child", i);
  318. cg_destroy(child);
  319. free(child);
  320. }
  321. cleanup:
  322. cg_destroy(parent);
  323. free(parent);
  324. return ret;
  325. }
  326. #define T(x) { x, #x }
  327. struct kmem_test {
  328. int (*fn)(const char *root);
  329. const char *name;
  330. } tests[] = {
  331. T(test_kmem_basic),
  332. T(test_kmem_memcg_deletion),
  333. T(test_kmem_proc_kpagecgroup),
  334. T(test_kmem_kernel_stacks),
  335. T(test_kmem_dead_cgroups),
  336. T(test_percpu_basic),
  337. };
  338. #undef T
  339. int main(int argc, char **argv)
  340. {
  341. char root[PATH_MAX];
  342. int i, ret = EXIT_SUCCESS;
  343. if (cg_find_unified_root(root, sizeof(root), NULL))
  344. ksft_exit_skip("cgroup v2 isn't mounted\n");
  345. /*
  346. * Check that memory controller is available:
  347. * memory is listed in cgroup.controllers
  348. */
  349. if (cg_read_strstr(root, "cgroup.controllers", "memory"))
  350. ksft_exit_skip("memory controller isn't available\n");
  351. if (cg_read_strstr(root, "cgroup.subtree_control", "memory"))
  352. if (cg_write(root, "cgroup.subtree_control", "+memory"))
  353. ksft_exit_skip("Failed to set memory controller\n");
  354. for (i = 0; i < ARRAY_SIZE(tests); i++) {
  355. switch (tests[i].fn(root)) {
  356. case KSFT_PASS:
  357. ksft_test_result_pass("%s\n", tests[i].name);
  358. break;
  359. case KSFT_SKIP:
  360. ksft_test_result_skip("%s\n", tests[i].name);
  361. break;
  362. default:
  363. ret = EXIT_FAILURE;
  364. ksft_test_result_fail("%s\n", tests[i].name);
  365. break;
  366. }
  367. }
  368. return ret;
  369. }