test_memcontrol.c 24 KB

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