test_memcontrol.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #define _GNU_SOURCE
  3. #include <linux/limits.h>
  4. #include <linux/oom.h>
  5. #include <fcntl.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/stat.h>
  10. #include <sys/types.h>
  11. #include <unistd.h>
  12. #include <sys/socket.h>
  13. #include <sys/wait.h>
  14. #include <arpa/inet.h>
  15. #include <netinet/in.h>
  16. #include <netdb.h>
  17. #include <errno.h>
  18. #include "../kselftest.h"
  19. #include "cgroup_util.h"
  20. /*
  21. * This test creates two nested cgroups with and without enabling
  22. * the memory controller.
  23. */
  24. static int test_memcg_subtree_control(const char *root)
  25. {
  26. char *parent, *child, *parent2 = NULL, *child2 = NULL;
  27. int ret = KSFT_FAIL;
  28. char buf[PAGE_SIZE];
  29. /* Create two nested cgroups with the memory controller enabled */
  30. parent = cg_name(root, "memcg_test_0");
  31. child = cg_name(root, "memcg_test_0/memcg_test_1");
  32. if (!parent || !child)
  33. goto cleanup_free;
  34. if (cg_create(parent))
  35. goto cleanup_free;
  36. if (cg_write(parent, "cgroup.subtree_control", "+memory"))
  37. goto cleanup_parent;
  38. if (cg_create(child))
  39. goto cleanup_parent;
  40. if (cg_read_strstr(child, "cgroup.controllers", "memory"))
  41. goto cleanup_child;
  42. /* Create two nested cgroups without enabling memory controller */
  43. parent2 = cg_name(root, "memcg_test_1");
  44. child2 = cg_name(root, "memcg_test_1/memcg_test_1");
  45. if (!parent2 || !child2)
  46. goto cleanup_free2;
  47. if (cg_create(parent2))
  48. goto cleanup_free2;
  49. if (cg_create(child2))
  50. goto cleanup_parent2;
  51. if (cg_read(child2, "cgroup.controllers", buf, sizeof(buf)))
  52. goto cleanup_all;
  53. if (!cg_read_strstr(child2, "cgroup.controllers", "memory"))
  54. goto cleanup_all;
  55. ret = KSFT_PASS;
  56. cleanup_all:
  57. cg_destroy(child2);
  58. cleanup_parent2:
  59. cg_destroy(parent2);
  60. cleanup_free2:
  61. free(parent2);
  62. free(child2);
  63. cleanup_child:
  64. cg_destroy(child);
  65. cleanup_parent:
  66. cg_destroy(parent);
  67. cleanup_free:
  68. free(parent);
  69. free(child);
  70. return ret;
  71. }
  72. static int alloc_anon_50M_check(const char *cgroup, void *arg)
  73. {
  74. size_t size = MB(50);
  75. char *buf, *ptr;
  76. long anon, current;
  77. int ret = -1;
  78. buf = malloc(size);
  79. for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
  80. *ptr = 0;
  81. current = cg_read_long(cgroup, "memory.current");
  82. if (current < size)
  83. goto cleanup;
  84. if (!values_close(size, current, 3))
  85. goto cleanup;
  86. anon = cg_read_key_long(cgroup, "memory.stat", "anon ");
  87. if (anon < 0)
  88. goto cleanup;
  89. if (!values_close(anon, current, 3))
  90. goto cleanup;
  91. ret = 0;
  92. cleanup:
  93. free(buf);
  94. return ret;
  95. }
  96. static int alloc_pagecache_50M_check(const char *cgroup, void *arg)
  97. {
  98. size_t size = MB(50);
  99. int ret = -1;
  100. long current, file;
  101. int fd;
  102. fd = get_temp_fd();
  103. if (fd < 0)
  104. return -1;
  105. if (alloc_pagecache(fd, size))
  106. goto cleanup;
  107. current = cg_read_long(cgroup, "memory.current");
  108. if (current < size)
  109. goto cleanup;
  110. file = cg_read_key_long(cgroup, "memory.stat", "file ");
  111. if (file < 0)
  112. goto cleanup;
  113. if (!values_close(file, current, 10))
  114. goto cleanup;
  115. ret = 0;
  116. cleanup:
  117. close(fd);
  118. return ret;
  119. }
  120. /*
  121. * This test create a memory cgroup, allocates
  122. * some anonymous memory and some pagecache
  123. * and check memory.current and some memory.stat values.
  124. */
  125. static int test_memcg_current(const char *root)
  126. {
  127. int ret = KSFT_FAIL;
  128. long current;
  129. char *memcg;
  130. memcg = cg_name(root, "memcg_test");
  131. if (!memcg)
  132. goto cleanup;
  133. if (cg_create(memcg))
  134. goto cleanup;
  135. current = cg_read_long(memcg, "memory.current");
  136. if (current != 0)
  137. goto cleanup;
  138. if (cg_run(memcg, alloc_anon_50M_check, NULL))
  139. goto cleanup;
  140. if (cg_run(memcg, alloc_pagecache_50M_check, NULL))
  141. goto cleanup;
  142. ret = KSFT_PASS;
  143. cleanup:
  144. cg_destroy(memcg);
  145. free(memcg);
  146. return ret;
  147. }
  148. static int alloc_pagecache_50M(const char *cgroup, void *arg)
  149. {
  150. int fd = (long)arg;
  151. return alloc_pagecache(fd, MB(50));
  152. }
  153. static int alloc_pagecache_50M_noexit(const char *cgroup, void *arg)
  154. {
  155. int fd = (long)arg;
  156. int ppid = getppid();
  157. if (alloc_pagecache(fd, MB(50)))
  158. return -1;
  159. while (getppid() == ppid)
  160. sleep(1);
  161. return 0;
  162. }
  163. static int alloc_anon_noexit(const char *cgroup, void *arg)
  164. {
  165. int ppid = getppid();
  166. if (alloc_anon(cgroup, arg))
  167. return -1;
  168. while (getppid() == ppid)
  169. sleep(1);
  170. return 0;
  171. }
  172. /*
  173. * Wait until processes are killed asynchronously by the OOM killer
  174. * If we exceed a timeout, fail.
  175. */
  176. static int cg_test_proc_killed(const char *cgroup)
  177. {
  178. int limit;
  179. for (limit = 10; limit > 0; limit--) {
  180. if (cg_read_strcmp(cgroup, "cgroup.procs", "") == 0)
  181. return 0;
  182. usleep(100000);
  183. }
  184. return -1;
  185. }
  186. /*
  187. * First, this test creates the following hierarchy:
  188. * A memory.min = 50M, memory.max = 200M
  189. * A/B memory.min = 50M, memory.current = 50M
  190. * A/B/C memory.min = 75M, memory.current = 50M
  191. * A/B/D memory.min = 25M, memory.current = 50M
  192. * A/B/E memory.min = 500M, memory.current = 0
  193. * A/B/F memory.min = 0, memory.current = 50M
  194. *
  195. * Usages are pagecache, but the test keeps a running
  196. * process in every leaf cgroup.
  197. * Then it creates A/G and creates a significant
  198. * memory pressure in it.
  199. *
  200. * A/B memory.current ~= 50M
  201. * A/B/C memory.current ~= 33M
  202. * A/B/D memory.current ~= 17M
  203. * A/B/E memory.current ~= 0
  204. *
  205. * After that it tries to allocate more than there is
  206. * unprotected memory in A available, and checks
  207. * checks that memory.min protects pagecache even
  208. * in this case.
  209. */
  210. static int test_memcg_min(const char *root)
  211. {
  212. int ret = KSFT_FAIL;
  213. char *parent[3] = {NULL};
  214. char *children[4] = {NULL};
  215. long c[4];
  216. int i, attempts;
  217. int fd;
  218. fd = get_temp_fd();
  219. if (fd < 0)
  220. goto cleanup;
  221. parent[0] = cg_name(root, "memcg_test_0");
  222. if (!parent[0])
  223. goto cleanup;
  224. parent[1] = cg_name(parent[0], "memcg_test_1");
  225. if (!parent[1])
  226. goto cleanup;
  227. parent[2] = cg_name(parent[0], "memcg_test_2");
  228. if (!parent[2])
  229. goto cleanup;
  230. if (cg_create(parent[0]))
  231. goto cleanup;
  232. if (cg_read_long(parent[0], "memory.min")) {
  233. ret = KSFT_SKIP;
  234. goto cleanup;
  235. }
  236. if (cg_write(parent[0], "cgroup.subtree_control", "+memory"))
  237. goto cleanup;
  238. if (cg_write(parent[0], "memory.max", "200M"))
  239. goto cleanup;
  240. if (cg_write(parent[0], "memory.swap.max", "0"))
  241. goto cleanup;
  242. if (cg_create(parent[1]))
  243. goto cleanup;
  244. if (cg_write(parent[1], "cgroup.subtree_control", "+memory"))
  245. goto cleanup;
  246. if (cg_create(parent[2]))
  247. goto cleanup;
  248. for (i = 0; i < ARRAY_SIZE(children); i++) {
  249. children[i] = cg_name_indexed(parent[1], "child_memcg", i);
  250. if (!children[i])
  251. goto cleanup;
  252. if (cg_create(children[i]))
  253. goto cleanup;
  254. if (i == 2)
  255. continue;
  256. cg_run_nowait(children[i], alloc_pagecache_50M_noexit,
  257. (void *)(long)fd);
  258. }
  259. if (cg_write(parent[0], "memory.min", "50M"))
  260. goto cleanup;
  261. if (cg_write(parent[1], "memory.min", "50M"))
  262. goto cleanup;
  263. if (cg_write(children[0], "memory.min", "75M"))
  264. goto cleanup;
  265. if (cg_write(children[1], "memory.min", "25M"))
  266. goto cleanup;
  267. if (cg_write(children[2], "memory.min", "500M"))
  268. goto cleanup;
  269. if (cg_write(children[3], "memory.min", "0"))
  270. goto cleanup;
  271. attempts = 0;
  272. while (!values_close(cg_read_long(parent[1], "memory.current"),
  273. MB(150), 3)) {
  274. if (attempts++ > 5)
  275. break;
  276. sleep(1);
  277. }
  278. if (cg_run(parent[2], alloc_anon, (void *)MB(148)))
  279. goto cleanup;
  280. if (!values_close(cg_read_long(parent[1], "memory.current"), MB(50), 3))
  281. goto cleanup;
  282. for (i = 0; i < ARRAY_SIZE(children); i++)
  283. c[i] = cg_read_long(children[i], "memory.current");
  284. if (!values_close(c[0], MB(33), 10))
  285. goto cleanup;
  286. if (!values_close(c[1], MB(17), 10))
  287. goto cleanup;
  288. if (!values_close(c[2], 0, 1))
  289. goto cleanup;
  290. if (!cg_run(parent[2], alloc_anon, (void *)MB(170)))
  291. goto cleanup;
  292. if (!values_close(cg_read_long(parent[1], "memory.current"), MB(50), 3))
  293. goto cleanup;
  294. ret = KSFT_PASS;
  295. cleanup:
  296. for (i = ARRAY_SIZE(children) - 1; i >= 0; i--) {
  297. if (!children[i])
  298. continue;
  299. cg_destroy(children[i]);
  300. free(children[i]);
  301. }
  302. for (i = ARRAY_SIZE(parent) - 1; i >= 0; i--) {
  303. if (!parent[i])
  304. continue;
  305. cg_destroy(parent[i]);
  306. free(parent[i]);
  307. }
  308. close(fd);
  309. return ret;
  310. }
  311. /*
  312. * First, this test creates the following hierarchy:
  313. * A memory.low = 50M, memory.max = 200M
  314. * A/B memory.low = 50M, memory.current = 50M
  315. * A/B/C memory.low = 75M, memory.current = 50M
  316. * A/B/D memory.low = 25M, memory.current = 50M
  317. * A/B/E memory.low = 500M, memory.current = 0
  318. * A/B/F memory.low = 0, memory.current = 50M
  319. *
  320. * Usages are pagecache.
  321. * Then it creates A/G an creates a significant
  322. * memory pressure in it.
  323. *
  324. * Then it checks actual memory usages and expects that:
  325. * A/B memory.current ~= 50M
  326. * A/B/ memory.current ~= 33M
  327. * A/B/D memory.current ~= 17M
  328. * A/B/E memory.current ~= 0
  329. *
  330. * After that it tries to allocate more than there is
  331. * unprotected memory in A available,
  332. * and checks low and oom events in memory.events.
  333. */
  334. static int test_memcg_low(const char *root)
  335. {
  336. int ret = KSFT_FAIL;
  337. char *parent[3] = {NULL};
  338. char *children[4] = {NULL};
  339. long low, oom;
  340. long c[4];
  341. int i;
  342. int fd;
  343. fd = get_temp_fd();
  344. if (fd < 0)
  345. goto cleanup;
  346. parent[0] = cg_name(root, "memcg_test_0");
  347. if (!parent[0])
  348. goto cleanup;
  349. parent[1] = cg_name(parent[0], "memcg_test_1");
  350. if (!parent[1])
  351. goto cleanup;
  352. parent[2] = cg_name(parent[0], "memcg_test_2");
  353. if (!parent[2])
  354. goto cleanup;
  355. if (cg_create(parent[0]))
  356. goto cleanup;
  357. if (cg_read_long(parent[0], "memory.low"))
  358. goto cleanup;
  359. if (cg_write(parent[0], "cgroup.subtree_control", "+memory"))
  360. goto cleanup;
  361. if (cg_write(parent[0], "memory.max", "200M"))
  362. goto cleanup;
  363. if (cg_write(parent[0], "memory.swap.max", "0"))
  364. goto cleanup;
  365. if (cg_create(parent[1]))
  366. goto cleanup;
  367. if (cg_write(parent[1], "cgroup.subtree_control", "+memory"))
  368. goto cleanup;
  369. if (cg_create(parent[2]))
  370. goto cleanup;
  371. for (i = 0; i < ARRAY_SIZE(children); i++) {
  372. children[i] = cg_name_indexed(parent[1], "child_memcg", i);
  373. if (!children[i])
  374. goto cleanup;
  375. if (cg_create(children[i]))
  376. goto cleanup;
  377. if (i == 2)
  378. continue;
  379. if (cg_run(children[i], alloc_pagecache_50M, (void *)(long)fd))
  380. goto cleanup;
  381. }
  382. if (cg_write(parent[0], "memory.low", "50M"))
  383. goto cleanup;
  384. if (cg_write(parent[1], "memory.low", "50M"))
  385. goto cleanup;
  386. if (cg_write(children[0], "memory.low", "75M"))
  387. goto cleanup;
  388. if (cg_write(children[1], "memory.low", "25M"))
  389. goto cleanup;
  390. if (cg_write(children[2], "memory.low", "500M"))
  391. goto cleanup;
  392. if (cg_write(children[3], "memory.low", "0"))
  393. goto cleanup;
  394. if (cg_run(parent[2], alloc_anon, (void *)MB(148)))
  395. goto cleanup;
  396. if (!values_close(cg_read_long(parent[1], "memory.current"), MB(50), 3))
  397. goto cleanup;
  398. for (i = 0; i < ARRAY_SIZE(children); i++)
  399. c[i] = cg_read_long(children[i], "memory.current");
  400. if (!values_close(c[0], MB(33), 10))
  401. goto cleanup;
  402. if (!values_close(c[1], MB(17), 10))
  403. goto cleanup;
  404. if (!values_close(c[2], 0, 1))
  405. goto cleanup;
  406. if (cg_run(parent[2], alloc_anon, (void *)MB(166))) {
  407. fprintf(stderr,
  408. "memory.low prevents from allocating anon memory\n");
  409. goto cleanup;
  410. }
  411. for (i = 0; i < ARRAY_SIZE(children); i++) {
  412. oom = cg_read_key_long(children[i], "memory.events", "oom ");
  413. low = cg_read_key_long(children[i], "memory.events", "low ");
  414. if (oom)
  415. goto cleanup;
  416. if (i < 2 && low <= 0)
  417. goto cleanup;
  418. if (i >= 2 && low)
  419. goto cleanup;
  420. }
  421. ret = KSFT_PASS;
  422. cleanup:
  423. for (i = ARRAY_SIZE(children) - 1; i >= 0; i--) {
  424. if (!children[i])
  425. continue;
  426. cg_destroy(children[i]);
  427. free(children[i]);
  428. }
  429. for (i = ARRAY_SIZE(parent) - 1; i >= 0; i--) {
  430. if (!parent[i])
  431. continue;
  432. cg_destroy(parent[i]);
  433. free(parent[i]);
  434. }
  435. close(fd);
  436. return ret;
  437. }
  438. static int alloc_pagecache_max_30M(const char *cgroup, void *arg)
  439. {
  440. size_t size = MB(50);
  441. int ret = -1;
  442. long current;
  443. int fd;
  444. fd = get_temp_fd();
  445. if (fd < 0)
  446. return -1;
  447. if (alloc_pagecache(fd, size))
  448. goto cleanup;
  449. current = cg_read_long(cgroup, "memory.current");
  450. if (current <= MB(29) || current > MB(30))
  451. goto cleanup;
  452. ret = 0;
  453. cleanup:
  454. close(fd);
  455. return ret;
  456. }
  457. /*
  458. * This test checks that memory.high limits the amount of
  459. * memory which can be consumed by either anonymous memory
  460. * or pagecache.
  461. */
  462. static int test_memcg_high(const char *root)
  463. {
  464. int ret = KSFT_FAIL;
  465. char *memcg;
  466. long high;
  467. memcg = cg_name(root, "memcg_test");
  468. if (!memcg)
  469. goto cleanup;
  470. if (cg_create(memcg))
  471. goto cleanup;
  472. if (cg_read_strcmp(memcg, "memory.high", "max\n"))
  473. goto cleanup;
  474. if (cg_write(memcg, "memory.swap.max", "0"))
  475. goto cleanup;
  476. if (cg_write(memcg, "memory.high", "30M"))
  477. goto cleanup;
  478. if (cg_run(memcg, alloc_anon, (void *)MB(100)))
  479. goto cleanup;
  480. if (!cg_run(memcg, alloc_pagecache_50M_check, NULL))
  481. goto cleanup;
  482. if (cg_run(memcg, alloc_pagecache_max_30M, NULL))
  483. goto cleanup;
  484. high = cg_read_key_long(memcg, "memory.events", "high ");
  485. if (high <= 0)
  486. goto cleanup;
  487. ret = KSFT_PASS;
  488. cleanup:
  489. cg_destroy(memcg);
  490. free(memcg);
  491. return ret;
  492. }
  493. /*
  494. * This test checks that memory.max limits the amount of
  495. * memory which can be consumed by either anonymous memory
  496. * or pagecache.
  497. */
  498. static int test_memcg_max(const char *root)
  499. {
  500. int ret = KSFT_FAIL;
  501. char *memcg;
  502. long current, max;
  503. memcg = cg_name(root, "memcg_test");
  504. if (!memcg)
  505. goto cleanup;
  506. if (cg_create(memcg))
  507. goto cleanup;
  508. if (cg_read_strcmp(memcg, "memory.max", "max\n"))
  509. goto cleanup;
  510. if (cg_write(memcg, "memory.swap.max", "0"))
  511. goto cleanup;
  512. if (cg_write(memcg, "memory.max", "30M"))
  513. goto cleanup;
  514. /* Should be killed by OOM killer */
  515. if (!cg_run(memcg, alloc_anon, (void *)MB(100)))
  516. goto cleanup;
  517. if (cg_run(memcg, alloc_pagecache_max_30M, NULL))
  518. goto cleanup;
  519. current = cg_read_long(memcg, "memory.current");
  520. if (current > MB(30) || !current)
  521. goto cleanup;
  522. max = cg_read_key_long(memcg, "memory.events", "max ");
  523. if (max <= 0)
  524. goto cleanup;
  525. ret = KSFT_PASS;
  526. cleanup:
  527. cg_destroy(memcg);
  528. free(memcg);
  529. return ret;
  530. }
  531. static int alloc_anon_50M_check_swap(const char *cgroup, void *arg)
  532. {
  533. long mem_max = (long)arg;
  534. size_t size = MB(50);
  535. char *buf, *ptr;
  536. long mem_current, swap_current;
  537. int ret = -1;
  538. buf = malloc(size);
  539. for (ptr = buf; ptr < buf + size; ptr += PAGE_SIZE)
  540. *ptr = 0;
  541. mem_current = cg_read_long(cgroup, "memory.current");
  542. if (!mem_current || !values_close(mem_current, mem_max, 3))
  543. goto cleanup;
  544. swap_current = cg_read_long(cgroup, "memory.swap.current");
  545. if (!swap_current ||
  546. !values_close(mem_current + swap_current, size, 3))
  547. goto cleanup;
  548. ret = 0;
  549. cleanup:
  550. free(buf);
  551. return ret;
  552. }
  553. /*
  554. * This test checks that memory.swap.max limits the amount of
  555. * anonymous memory which can be swapped out.
  556. */
  557. static int test_memcg_swap_max(const char *root)
  558. {
  559. int ret = KSFT_FAIL;
  560. char *memcg;
  561. long max;
  562. if (!is_swap_enabled())
  563. return KSFT_SKIP;
  564. memcg = cg_name(root, "memcg_test");
  565. if (!memcg)
  566. goto cleanup;
  567. if (cg_create(memcg))
  568. goto cleanup;
  569. if (cg_read_long(memcg, "memory.swap.current")) {
  570. ret = KSFT_SKIP;
  571. goto cleanup;
  572. }
  573. if (cg_read_strcmp(memcg, "memory.max", "max\n"))
  574. goto cleanup;
  575. if (cg_read_strcmp(memcg, "memory.swap.max", "max\n"))
  576. goto cleanup;
  577. if (cg_write(memcg, "memory.swap.max", "30M"))
  578. goto cleanup;
  579. if (cg_write(memcg, "memory.max", "30M"))
  580. goto cleanup;
  581. /* Should be killed by OOM killer */
  582. if (!cg_run(memcg, alloc_anon, (void *)MB(100)))
  583. goto cleanup;
  584. if (cg_read_key_long(memcg, "memory.events", "oom ") != 1)
  585. goto cleanup;
  586. if (cg_read_key_long(memcg, "memory.events", "oom_kill ") != 1)
  587. goto cleanup;
  588. if (cg_run(memcg, alloc_anon_50M_check_swap, (void *)MB(30)))
  589. goto cleanup;
  590. max = cg_read_key_long(memcg, "memory.events", "max ");
  591. if (max <= 0)
  592. goto cleanup;
  593. ret = KSFT_PASS;
  594. cleanup:
  595. cg_destroy(memcg);
  596. free(memcg);
  597. return ret;
  598. }
  599. /*
  600. * This test disables swapping and tries to allocate anonymous memory
  601. * up to OOM. Then it checks for oom and oom_kill events in
  602. * memory.events.
  603. */
  604. static int test_memcg_oom_events(const char *root)
  605. {
  606. int ret = KSFT_FAIL;
  607. char *memcg;
  608. memcg = cg_name(root, "memcg_test");
  609. if (!memcg)
  610. goto cleanup;
  611. if (cg_create(memcg))
  612. goto cleanup;
  613. if (cg_write(memcg, "memory.max", "30M"))
  614. goto cleanup;
  615. if (cg_write(memcg, "memory.swap.max", "0"))
  616. goto cleanup;
  617. if (!cg_run(memcg, alloc_anon, (void *)MB(100)))
  618. goto cleanup;
  619. if (cg_read_strcmp(memcg, "cgroup.procs", ""))
  620. goto cleanup;
  621. if (cg_read_key_long(memcg, "memory.events", "oom ") != 1)
  622. goto cleanup;
  623. if (cg_read_key_long(memcg, "memory.events", "oom_kill ") != 1)
  624. goto cleanup;
  625. ret = KSFT_PASS;
  626. cleanup:
  627. cg_destroy(memcg);
  628. free(memcg);
  629. return ret;
  630. }
  631. struct tcp_server_args {
  632. unsigned short port;
  633. int ctl[2];
  634. };
  635. static int tcp_server(const char *cgroup, void *arg)
  636. {
  637. struct tcp_server_args *srv_args = arg;
  638. struct sockaddr_in6 saddr = { 0 };
  639. socklen_t slen = sizeof(saddr);
  640. int sk, client_sk, ctl_fd, yes = 1, ret = -1;
  641. close(srv_args->ctl[0]);
  642. ctl_fd = srv_args->ctl[1];
  643. saddr.sin6_family = AF_INET6;
  644. saddr.sin6_addr = in6addr_any;
  645. saddr.sin6_port = htons(srv_args->port);
  646. sk = socket(AF_INET6, SOCK_STREAM, 0);
  647. if (sk < 0)
  648. return ret;
  649. if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0)
  650. goto cleanup;
  651. if (bind(sk, (struct sockaddr *)&saddr, slen)) {
  652. write(ctl_fd, &errno, sizeof(errno));
  653. goto cleanup;
  654. }
  655. if (listen(sk, 1))
  656. goto cleanup;
  657. ret = 0;
  658. if (write(ctl_fd, &ret, sizeof(ret)) != sizeof(ret)) {
  659. ret = -1;
  660. goto cleanup;
  661. }
  662. client_sk = accept(sk, NULL, NULL);
  663. if (client_sk < 0)
  664. goto cleanup;
  665. ret = -1;
  666. for (;;) {
  667. uint8_t buf[0x100000];
  668. if (write(client_sk, buf, sizeof(buf)) <= 0) {
  669. if (errno == ECONNRESET)
  670. ret = 0;
  671. break;
  672. }
  673. }
  674. close(client_sk);
  675. cleanup:
  676. close(sk);
  677. return ret;
  678. }
  679. static int tcp_client(const char *cgroup, unsigned short port)
  680. {
  681. const char server[] = "localhost";
  682. struct addrinfo *ai;
  683. char servport[6];
  684. int retries = 0x10; /* nice round number */
  685. int sk, ret;
  686. snprintf(servport, sizeof(servport), "%hd", port);
  687. ret = getaddrinfo(server, servport, NULL, &ai);
  688. if (ret)
  689. return ret;
  690. sk = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  691. if (sk < 0)
  692. goto free_ainfo;
  693. ret = connect(sk, ai->ai_addr, ai->ai_addrlen);
  694. if (ret < 0)
  695. goto close_sk;
  696. ret = KSFT_FAIL;
  697. while (retries--) {
  698. uint8_t buf[0x100000];
  699. long current, sock;
  700. if (read(sk, buf, sizeof(buf)) <= 0)
  701. goto close_sk;
  702. current = cg_read_long(cgroup, "memory.current");
  703. sock = cg_read_key_long(cgroup, "memory.stat", "sock ");
  704. if (current < 0 || sock < 0)
  705. goto close_sk;
  706. if (current < sock)
  707. goto close_sk;
  708. if (values_close(current, sock, 10)) {
  709. ret = KSFT_PASS;
  710. break;
  711. }
  712. }
  713. close_sk:
  714. close(sk);
  715. free_ainfo:
  716. freeaddrinfo(ai);
  717. return ret;
  718. }
  719. /*
  720. * This test checks socket memory accounting.
  721. * The test forks a TCP server listens on a random port between 1000
  722. * and 61000. Once it gets a client connection, it starts writing to
  723. * its socket.
  724. * The TCP client interleaves reads from the socket with check whether
  725. * memory.current and memory.stat.sock are similar.
  726. */
  727. static int test_memcg_sock(const char *root)
  728. {
  729. int bind_retries = 5, ret = KSFT_FAIL, pid, err;
  730. unsigned short port;
  731. char *memcg;
  732. memcg = cg_name(root, "memcg_test");
  733. if (!memcg)
  734. goto cleanup;
  735. if (cg_create(memcg))
  736. goto cleanup;
  737. while (bind_retries--) {
  738. struct tcp_server_args args;
  739. if (pipe(args.ctl))
  740. goto cleanup;
  741. port = args.port = 1000 + rand() % 60000;
  742. pid = cg_run_nowait(memcg, tcp_server, &args);
  743. if (pid < 0)
  744. goto cleanup;
  745. close(args.ctl[1]);
  746. if (read(args.ctl[0], &err, sizeof(err)) != sizeof(err))
  747. goto cleanup;
  748. close(args.ctl[0]);
  749. if (!err)
  750. break;
  751. if (err != EADDRINUSE)
  752. goto cleanup;
  753. waitpid(pid, NULL, 0);
  754. }
  755. if (err == EADDRINUSE) {
  756. ret = KSFT_SKIP;
  757. goto cleanup;
  758. }
  759. if (tcp_client(memcg, port) != KSFT_PASS)
  760. goto cleanup;
  761. waitpid(pid, &err, 0);
  762. if (WEXITSTATUS(err))
  763. goto cleanup;
  764. if (cg_read_long(memcg, "memory.current") < 0)
  765. goto cleanup;
  766. if (cg_read_key_long(memcg, "memory.stat", "sock "))
  767. goto cleanup;
  768. ret = KSFT_PASS;
  769. cleanup:
  770. cg_destroy(memcg);
  771. free(memcg);
  772. return ret;
  773. }
  774. /*
  775. * This test disables swapping and tries to allocate anonymous memory
  776. * up to OOM with memory.group.oom set. Then it checks that all
  777. * processes in the leaf (but not the parent) were killed.
  778. */
  779. static int test_memcg_oom_group_leaf_events(const char *root)
  780. {
  781. int ret = KSFT_FAIL;
  782. char *parent, *child;
  783. parent = cg_name(root, "memcg_test_0");
  784. child = cg_name(root, "memcg_test_0/memcg_test_1");
  785. if (!parent || !child)
  786. goto cleanup;
  787. if (cg_create(parent))
  788. goto cleanup;
  789. if (cg_create(child))
  790. goto cleanup;
  791. if (cg_write(parent, "cgroup.subtree_control", "+memory"))
  792. goto cleanup;
  793. if (cg_write(child, "memory.max", "50M"))
  794. goto cleanup;
  795. if (cg_write(child, "memory.swap.max", "0"))
  796. goto cleanup;
  797. if (cg_write(child, "memory.oom.group", "1"))
  798. goto cleanup;
  799. cg_run_nowait(parent, alloc_anon_noexit, (void *) MB(60));
  800. cg_run_nowait(child, alloc_anon_noexit, (void *) MB(1));
  801. cg_run_nowait(child, alloc_anon_noexit, (void *) MB(1));
  802. if (!cg_run(child, alloc_anon, (void *)MB(100)))
  803. goto cleanup;
  804. if (cg_test_proc_killed(child))
  805. goto cleanup;
  806. if (cg_read_key_long(child, "memory.events", "oom_kill ") <= 0)
  807. goto cleanup;
  808. if (cg_read_key_long(parent, "memory.events", "oom_kill ") != 0)
  809. goto cleanup;
  810. ret = KSFT_PASS;
  811. cleanup:
  812. if (child)
  813. cg_destroy(child);
  814. if (parent)
  815. cg_destroy(parent);
  816. free(child);
  817. free(parent);
  818. return ret;
  819. }
  820. /*
  821. * This test disables swapping and tries to allocate anonymous memory
  822. * up to OOM with memory.group.oom set. Then it checks that all
  823. * processes in the parent and leaf were killed.
  824. */
  825. static int test_memcg_oom_group_parent_events(const char *root)
  826. {
  827. int ret = KSFT_FAIL;
  828. char *parent, *child;
  829. parent = cg_name(root, "memcg_test_0");
  830. child = cg_name(root, "memcg_test_0/memcg_test_1");
  831. if (!parent || !child)
  832. goto cleanup;
  833. if (cg_create(parent))
  834. goto cleanup;
  835. if (cg_create(child))
  836. goto cleanup;
  837. if (cg_write(parent, "memory.max", "80M"))
  838. goto cleanup;
  839. if (cg_write(parent, "memory.swap.max", "0"))
  840. goto cleanup;
  841. if (cg_write(parent, "memory.oom.group", "1"))
  842. goto cleanup;
  843. cg_run_nowait(parent, alloc_anon_noexit, (void *) MB(60));
  844. cg_run_nowait(child, alloc_anon_noexit, (void *) MB(1));
  845. cg_run_nowait(child, alloc_anon_noexit, (void *) MB(1));
  846. if (!cg_run(child, alloc_anon, (void *)MB(100)))
  847. goto cleanup;
  848. if (cg_test_proc_killed(child))
  849. goto cleanup;
  850. if (cg_test_proc_killed(parent))
  851. goto cleanup;
  852. ret = KSFT_PASS;
  853. cleanup:
  854. if (child)
  855. cg_destroy(child);
  856. if (parent)
  857. cg_destroy(parent);
  858. free(child);
  859. free(parent);
  860. return ret;
  861. }
  862. /*
  863. * This test disables swapping and tries to allocate anonymous memory
  864. * up to OOM with memory.group.oom set. Then it checks that all
  865. * processes were killed except those set with OOM_SCORE_ADJ_MIN
  866. */
  867. static int test_memcg_oom_group_score_events(const char *root)
  868. {
  869. int ret = KSFT_FAIL;
  870. char *memcg;
  871. int safe_pid;
  872. memcg = cg_name(root, "memcg_test_0");
  873. if (!memcg)
  874. goto cleanup;
  875. if (cg_create(memcg))
  876. goto cleanup;
  877. if (cg_write(memcg, "memory.max", "50M"))
  878. goto cleanup;
  879. if (cg_write(memcg, "memory.swap.max", "0"))
  880. goto cleanup;
  881. if (cg_write(memcg, "memory.oom.group", "1"))
  882. goto cleanup;
  883. safe_pid = cg_run_nowait(memcg, alloc_anon_noexit, (void *) MB(1));
  884. if (set_oom_adj_score(safe_pid, OOM_SCORE_ADJ_MIN))
  885. goto cleanup;
  886. cg_run_nowait(memcg, alloc_anon_noexit, (void *) MB(1));
  887. if (!cg_run(memcg, alloc_anon, (void *)MB(100)))
  888. goto cleanup;
  889. if (cg_read_key_long(memcg, "memory.events", "oom_kill ") != 3)
  890. goto cleanup;
  891. if (kill(safe_pid, SIGKILL))
  892. goto cleanup;
  893. ret = KSFT_PASS;
  894. cleanup:
  895. if (memcg)
  896. cg_destroy(memcg);
  897. free(memcg);
  898. return ret;
  899. }
  900. #define T(x) { x, #x }
  901. struct memcg_test {
  902. int (*fn)(const char *root);
  903. const char *name;
  904. } tests[] = {
  905. T(test_memcg_subtree_control),
  906. T(test_memcg_current),
  907. T(test_memcg_min),
  908. T(test_memcg_low),
  909. T(test_memcg_high),
  910. T(test_memcg_max),
  911. T(test_memcg_oom_events),
  912. T(test_memcg_swap_max),
  913. T(test_memcg_sock),
  914. T(test_memcg_oom_group_leaf_events),
  915. T(test_memcg_oom_group_parent_events),
  916. T(test_memcg_oom_group_score_events),
  917. };
  918. #undef T
  919. int main(int argc, char **argv)
  920. {
  921. char root[PATH_MAX];
  922. int i, ret = EXIT_SUCCESS;
  923. if (cg_find_unified_root(root, sizeof(root)))
  924. ksft_exit_skip("cgroup v2 isn't mounted\n");
  925. /*
  926. * Check that memory controller is available:
  927. * memory is listed in cgroup.controllers
  928. */
  929. if (cg_read_strstr(root, "cgroup.controllers", "memory"))
  930. ksft_exit_skip("memory controller isn't available\n");
  931. if (cg_read_strstr(root, "cgroup.subtree_control", "memory"))
  932. if (cg_write(root, "cgroup.subtree_control", "+memory"))
  933. ksft_exit_skip("Failed to set memory controller\n");
  934. for (i = 0; i < ARRAY_SIZE(tests); i++) {
  935. switch (tests[i].fn(root)) {
  936. case KSFT_PASS:
  937. ksft_test_result_pass("%s\n", tests[i].name);
  938. break;
  939. case KSFT_SKIP:
  940. ksft_test_result_skip("%s\n", tests[i].name);
  941. break;
  942. default:
  943. ret = EXIT_FAILURE;
  944. ksft_test_result_fail("%s\n", tests[i].name);
  945. break;
  946. }
  947. }
  948. return ret;
  949. }