core-kunit.h 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Data Access Monitor Unit Tests
  4. *
  5. * Copyright 2019 Amazon.com, Inc. or its affiliates. All rights reserved.
  6. *
  7. * Author: SeongJae Park <sj@kernel.org>
  8. */
  9. #ifdef CONFIG_DAMON_KUNIT_TEST
  10. #ifndef _DAMON_CORE_TEST_H
  11. #define _DAMON_CORE_TEST_H
  12. #include <kunit/test.h>
  13. static void damon_test_regions(struct kunit *test)
  14. {
  15. struct damon_region *r;
  16. struct damon_target *t;
  17. r = damon_new_region(1, 2);
  18. if (!r)
  19. kunit_skip(test, "region alloc fail");
  20. KUNIT_EXPECT_EQ(test, 1ul, r->ar.start);
  21. KUNIT_EXPECT_EQ(test, 2ul, r->ar.end);
  22. KUNIT_EXPECT_EQ(test, 0u, r->nr_accesses);
  23. t = damon_new_target();
  24. if (!t) {
  25. damon_free_region(r);
  26. kunit_skip(test, "target alloc fail");
  27. }
  28. KUNIT_EXPECT_EQ(test, 0u, damon_nr_regions(t));
  29. damon_add_region(r, t);
  30. KUNIT_EXPECT_EQ(test, 1u, damon_nr_regions(t));
  31. damon_destroy_region(r, t);
  32. KUNIT_EXPECT_EQ(test, 0u, damon_nr_regions(t));
  33. damon_free_target(t);
  34. }
  35. static unsigned int nr_damon_targets(struct damon_ctx *ctx)
  36. {
  37. struct damon_target *t;
  38. unsigned int nr_targets = 0;
  39. damon_for_each_target(t, ctx)
  40. nr_targets++;
  41. return nr_targets;
  42. }
  43. static void damon_test_target(struct kunit *test)
  44. {
  45. struct damon_ctx *c = damon_new_ctx();
  46. struct damon_target *t;
  47. if (!c)
  48. kunit_skip(test, "ctx alloc fail");
  49. t = damon_new_target();
  50. if (!t) {
  51. damon_destroy_ctx(c);
  52. kunit_skip(test, "target alloc fail");
  53. }
  54. KUNIT_EXPECT_EQ(test, 0u, nr_damon_targets(c));
  55. damon_add_target(c, t);
  56. KUNIT_EXPECT_EQ(test, 1u, nr_damon_targets(c));
  57. damon_destroy_target(t, c);
  58. KUNIT_EXPECT_EQ(test, 0u, nr_damon_targets(c));
  59. damon_destroy_ctx(c);
  60. }
  61. /*
  62. * Test kdamond_reset_aggregated()
  63. *
  64. * DAMON checks access to each region and aggregates this information as the
  65. * access frequency of each region. In detail, it increases '->nr_accesses' of
  66. * regions that an access has confirmed. 'kdamond_reset_aggregated()' flushes
  67. * the aggregated information ('->nr_accesses' of each regions) to the result
  68. * buffer. As a result of the flushing, the '->nr_accesses' of regions are
  69. * initialized to zero.
  70. */
  71. static void damon_test_aggregate(struct kunit *test)
  72. {
  73. struct damon_ctx *ctx = damon_new_ctx();
  74. unsigned long saddr[][3] = {{10, 20, 30}, {5, 42, 49}, {13, 33, 55} };
  75. unsigned long eaddr[][3] = {{15, 27, 40}, {31, 45, 55}, {23, 44, 66} };
  76. unsigned long accesses[][3] = {{42, 95, 84}, {10, 20, 30}, {0, 1, 2} };
  77. struct damon_target *t;
  78. struct damon_region *r;
  79. int it, ir;
  80. if (!ctx)
  81. kunit_skip(test, "ctx alloc fail");
  82. for (it = 0; it < 3; it++) {
  83. t = damon_new_target();
  84. if (!t) {
  85. damon_destroy_ctx(ctx);
  86. kunit_skip(test, "target alloc fail");
  87. }
  88. damon_add_target(ctx, t);
  89. }
  90. it = 0;
  91. damon_for_each_target(t, ctx) {
  92. for (ir = 0; ir < 3; ir++) {
  93. r = damon_new_region(saddr[it][ir], eaddr[it][ir]);
  94. if (!r) {
  95. damon_destroy_ctx(ctx);
  96. kunit_skip(test, "region alloc fail");
  97. }
  98. r->nr_accesses = accesses[it][ir];
  99. r->nr_accesses_bp = accesses[it][ir] * 10000;
  100. damon_add_region(r, t);
  101. }
  102. it++;
  103. }
  104. kdamond_reset_aggregated(ctx);
  105. it = 0;
  106. damon_for_each_target(t, ctx) {
  107. ir = 0;
  108. /* '->nr_accesses' should be zeroed */
  109. damon_for_each_region(r, t) {
  110. KUNIT_EXPECT_EQ(test, 0u, r->nr_accesses);
  111. ir++;
  112. }
  113. /* regions should be preserved */
  114. KUNIT_EXPECT_EQ(test, 3, ir);
  115. it++;
  116. }
  117. /* targets also should be preserved */
  118. KUNIT_EXPECT_EQ(test, 3, it);
  119. damon_destroy_ctx(ctx);
  120. }
  121. static void damon_test_split_at(struct kunit *test)
  122. {
  123. struct damon_target *t;
  124. struct damon_region *r, *r_new;
  125. t = damon_new_target();
  126. if (!t)
  127. kunit_skip(test, "target alloc fail");
  128. r = damon_new_region(0, 100);
  129. if (!r) {
  130. damon_free_target(t);
  131. kunit_skip(test, "region alloc fail");
  132. }
  133. r->nr_accesses_bp = 420000;
  134. r->nr_accesses = 42;
  135. r->last_nr_accesses = 15;
  136. r->age = 10;
  137. damon_add_region(r, t);
  138. damon_split_region_at(t, r, 25);
  139. KUNIT_EXPECT_EQ(test, r->ar.start, 0ul);
  140. KUNIT_EXPECT_EQ(test, r->ar.end, 25ul);
  141. r_new = damon_next_region(r);
  142. KUNIT_EXPECT_EQ(test, r_new->ar.start, 25ul);
  143. KUNIT_EXPECT_EQ(test, r_new->ar.end, 100ul);
  144. KUNIT_EXPECT_EQ(test, r->nr_accesses_bp, r_new->nr_accesses_bp);
  145. KUNIT_EXPECT_EQ(test, r->nr_accesses, r_new->nr_accesses);
  146. KUNIT_EXPECT_EQ(test, r->last_nr_accesses, r_new->last_nr_accesses);
  147. KUNIT_EXPECT_EQ(test, r->age, r_new->age);
  148. damon_free_target(t);
  149. }
  150. static void damon_test_merge_two(struct kunit *test)
  151. {
  152. struct damon_target *t;
  153. struct damon_region *r, *r2, *r3;
  154. int i;
  155. t = damon_new_target();
  156. if (!t)
  157. kunit_skip(test, "target alloc fail");
  158. r = damon_new_region(0, 100);
  159. if (!r) {
  160. damon_free_target(t);
  161. kunit_skip(test, "region alloc fail");
  162. }
  163. r->nr_accesses = 10;
  164. r->nr_accesses_bp = 100000;
  165. r->age = 9;
  166. damon_add_region(r, t);
  167. r2 = damon_new_region(100, 300);
  168. if (!r2) {
  169. damon_free_target(t);
  170. kunit_skip(test, "second region alloc fail");
  171. }
  172. r2->nr_accesses = 20;
  173. r2->nr_accesses_bp = 200000;
  174. r2->age = 21;
  175. damon_add_region(r2, t);
  176. damon_merge_two_regions(t, r, r2);
  177. KUNIT_EXPECT_EQ(test, r->ar.start, 0ul);
  178. KUNIT_EXPECT_EQ(test, r->ar.end, 300ul);
  179. KUNIT_EXPECT_EQ(test, r->nr_accesses, 16u);
  180. KUNIT_EXPECT_EQ(test, r->nr_accesses_bp, 160000u);
  181. KUNIT_EXPECT_EQ(test, r->age, 17u);
  182. i = 0;
  183. damon_for_each_region(r3, t) {
  184. KUNIT_EXPECT_PTR_EQ(test, r, r3);
  185. i++;
  186. }
  187. KUNIT_EXPECT_EQ(test, i, 1);
  188. damon_free_target(t);
  189. }
  190. static struct damon_region *__nth_region_of(struct damon_target *t, int idx)
  191. {
  192. struct damon_region *r;
  193. unsigned int i = 0;
  194. damon_for_each_region(r, t) {
  195. if (i++ == idx)
  196. return r;
  197. }
  198. return NULL;
  199. }
  200. static void damon_test_merge_regions_of(struct kunit *test)
  201. {
  202. struct damon_target *t;
  203. struct damon_region *r;
  204. unsigned long sa[] = {0, 100, 114, 122, 130, 156, 170, 184, 230};
  205. unsigned long ea[] = {100, 112, 122, 130, 156, 170, 184, 230, 10170};
  206. unsigned int nrs[] = {0, 0, 10, 10, 20, 30, 1, 2, 5};
  207. unsigned long saddrs[] = {0, 114, 130, 156, 170, 230};
  208. unsigned long eaddrs[] = {112, 130, 156, 170, 230, 10170};
  209. int i;
  210. t = damon_new_target();
  211. if (!t)
  212. kunit_skip(test, "target alloc fail");
  213. for (i = 0; i < ARRAY_SIZE(sa); i++) {
  214. r = damon_new_region(sa[i], ea[i]);
  215. if (!r) {
  216. damon_free_target(t);
  217. kunit_skip(test, "region alloc fail");
  218. }
  219. r->nr_accesses = nrs[i];
  220. r->nr_accesses_bp = nrs[i] * 10000;
  221. damon_add_region(r, t);
  222. }
  223. damon_merge_regions_of(t, 9, 9999);
  224. /* 0-112, 114-130, 130-156, 156-170, 170-230, 230-10170 */
  225. KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 6u);
  226. for (i = 0; i < 6; i++) {
  227. r = __nth_region_of(t, i);
  228. KUNIT_EXPECT_EQ(test, r->ar.start, saddrs[i]);
  229. KUNIT_EXPECT_EQ(test, r->ar.end, eaddrs[i]);
  230. }
  231. damon_free_target(t);
  232. }
  233. static void damon_test_split_regions_of(struct kunit *test)
  234. {
  235. struct damon_target *t;
  236. struct damon_region *r;
  237. unsigned long sa[] = {0, 300, 500};
  238. unsigned long ea[] = {220, 400, 700};
  239. int i;
  240. t = damon_new_target();
  241. if (!t)
  242. kunit_skip(test, "target alloc fail");
  243. r = damon_new_region(0, 22);
  244. if (!r) {
  245. damon_free_target(t);
  246. kunit_skip(test, "region alloc fail");
  247. }
  248. damon_add_region(r, t);
  249. damon_split_regions_of(t, 2, 1);
  250. KUNIT_EXPECT_LE(test, damon_nr_regions(t), 2u);
  251. damon_free_target(t);
  252. t = damon_new_target();
  253. if (!t)
  254. kunit_skip(test, "second target alloc fail");
  255. r = damon_new_region(0, 220);
  256. if (!r) {
  257. damon_free_target(t);
  258. kunit_skip(test, "second region alloc fail");
  259. }
  260. damon_add_region(r, t);
  261. damon_split_regions_of(t, 4, 1);
  262. KUNIT_EXPECT_LE(test, damon_nr_regions(t), 4u);
  263. damon_free_target(t);
  264. t = damon_new_target();
  265. if (!t)
  266. kunit_skip(test, "third target alloc fail");
  267. for (i = 0; i < ARRAY_SIZE(sa); i++) {
  268. r = damon_new_region(sa[i], ea[i]);
  269. if (!r) {
  270. damon_free_target(t);
  271. kunit_skip(test, "region alloc fail");
  272. }
  273. damon_add_region(r, t);
  274. }
  275. damon_split_regions_of(t, 4, 5);
  276. KUNIT_EXPECT_LE(test, damon_nr_regions(t), 12u);
  277. damon_for_each_region(r, t)
  278. KUNIT_EXPECT_GE(test, damon_sz_region(r) % 5ul, 0ul);
  279. damon_free_target(t);
  280. }
  281. static void damon_test_ops_registration(struct kunit *test)
  282. {
  283. struct damon_ctx *c = damon_new_ctx();
  284. struct damon_operations ops = {.id = DAMON_OPS_VADDR}, bak;
  285. bool need_cleanup = false;
  286. if (!c)
  287. kunit_skip(test, "ctx alloc fail");
  288. /* DAMON_OPS_VADDR is registered only if CONFIG_DAMON_VADDR is set */
  289. if (!damon_is_registered_ops(DAMON_OPS_VADDR)) {
  290. bak.id = DAMON_OPS_VADDR;
  291. KUNIT_EXPECT_EQ(test, damon_register_ops(&bak), 0);
  292. need_cleanup = true;
  293. }
  294. /* DAMON_OPS_VADDR is ensured to be registered */
  295. KUNIT_EXPECT_EQ(test, damon_select_ops(c, DAMON_OPS_VADDR), 0);
  296. /* Double-registration is prohibited */
  297. KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), -EINVAL);
  298. /* Unknown ops id cannot be registered */
  299. KUNIT_EXPECT_EQ(test, damon_select_ops(c, NR_DAMON_OPS), -EINVAL);
  300. /* Registration should success after unregistration */
  301. mutex_lock(&damon_ops_lock);
  302. bak = damon_registered_ops[DAMON_OPS_VADDR];
  303. damon_registered_ops[DAMON_OPS_VADDR] = (struct damon_operations){};
  304. mutex_unlock(&damon_ops_lock);
  305. ops.id = DAMON_OPS_VADDR;
  306. KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), 0);
  307. mutex_lock(&damon_ops_lock);
  308. damon_registered_ops[DAMON_OPS_VADDR] = bak;
  309. mutex_unlock(&damon_ops_lock);
  310. /* Check double-registration failure again */
  311. KUNIT_EXPECT_EQ(test, damon_register_ops(&ops), -EINVAL);
  312. damon_destroy_ctx(c);
  313. if (need_cleanup) {
  314. mutex_lock(&damon_ops_lock);
  315. damon_registered_ops[DAMON_OPS_VADDR] =
  316. (struct damon_operations){};
  317. mutex_unlock(&damon_ops_lock);
  318. }
  319. }
  320. static void damon_test_set_regions(struct kunit *test)
  321. {
  322. struct damon_target *t = damon_new_target();
  323. struct damon_region *r1, *r2;
  324. struct damon_addr_range range = {.start = 8, .end = 28};
  325. unsigned long expects[] = {8, 16, 16, 24, 24, 28};
  326. int expect_idx = 0;
  327. struct damon_region *r;
  328. if (!t)
  329. kunit_skip(test, "target alloc fail");
  330. r1 = damon_new_region(4, 16);
  331. if (!r1) {
  332. damon_free_target(t);
  333. kunit_skip(test, "region alloc fail");
  334. }
  335. r2 = damon_new_region(24, 32);
  336. if (!r2) {
  337. damon_free_target(t);
  338. damon_free_region(r1);
  339. kunit_skip(test, "second region alloc fail");
  340. }
  341. damon_add_region(r1, t);
  342. damon_add_region(r2, t);
  343. damon_set_regions(t, &range, 1, 1);
  344. KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 3);
  345. damon_for_each_region(r, t) {
  346. KUNIT_EXPECT_EQ(test, r->ar.start, expects[expect_idx++]);
  347. KUNIT_EXPECT_EQ(test, r->ar.end, expects[expect_idx++]);
  348. }
  349. damon_destroy_target(t, NULL);
  350. }
  351. static void damon_test_nr_accesses_to_accesses_bp(struct kunit *test)
  352. {
  353. struct damon_attrs attrs = {
  354. .sample_interval = 10,
  355. .aggr_interval = ((unsigned long)UINT_MAX + 1) * 10
  356. };
  357. /*
  358. * In some cases such as 32bit architectures where UINT_MAX is
  359. * ULONG_MAX, attrs.aggr_interval becomes zero. Calling
  360. * damon_nr_accesses_to_accesses_bp() in the case will cause
  361. * divide-by-zero. Such case is prohibited in normal execution since
  362. * the caution is documented on the comment for the function, and
  363. * damon_update_monitoring_results() does the check. Skip the test in
  364. * the case.
  365. */
  366. if (!attrs.aggr_interval)
  367. kunit_skip(test, "aggr_interval is zero.");
  368. KUNIT_EXPECT_EQ(test, damon_nr_accesses_to_accesses_bp(123, &attrs), 0);
  369. }
  370. static void damon_test_update_monitoring_result(struct kunit *test)
  371. {
  372. struct damon_attrs old_attrs = {
  373. .sample_interval = 10, .aggr_interval = 1000,};
  374. struct damon_attrs new_attrs;
  375. struct damon_region *r = damon_new_region(3, 7);
  376. if (!r)
  377. kunit_skip(test, "region alloc fail");
  378. r->nr_accesses = 15;
  379. r->nr_accesses_bp = 150000;
  380. r->age = 20;
  381. new_attrs = (struct damon_attrs){
  382. .sample_interval = 100, .aggr_interval = 10000,};
  383. damon_update_monitoring_result(r, &old_attrs, &new_attrs, false);
  384. KUNIT_EXPECT_EQ(test, r->nr_accesses, 15);
  385. KUNIT_EXPECT_EQ(test, r->age, 2);
  386. new_attrs = (struct damon_attrs){
  387. .sample_interval = 1, .aggr_interval = 1000};
  388. damon_update_monitoring_result(r, &old_attrs, &new_attrs, false);
  389. KUNIT_EXPECT_EQ(test, r->nr_accesses, 150);
  390. KUNIT_EXPECT_EQ(test, r->age, 2);
  391. new_attrs = (struct damon_attrs){
  392. .sample_interval = 1, .aggr_interval = 100};
  393. damon_update_monitoring_result(r, &old_attrs, &new_attrs, false);
  394. KUNIT_EXPECT_EQ(test, r->nr_accesses, 150);
  395. KUNIT_EXPECT_EQ(test, r->age, 20);
  396. damon_free_region(r);
  397. }
  398. static void damon_test_set_attrs(struct kunit *test)
  399. {
  400. struct damon_ctx *c = damon_new_ctx();
  401. struct damon_attrs valid_attrs = {
  402. .min_nr_regions = 10, .max_nr_regions = 1000,
  403. .sample_interval = 5000, .aggr_interval = 100000,};
  404. struct damon_attrs invalid_attrs;
  405. if (!c)
  406. kunit_skip(test, "ctx alloc fail");
  407. KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &valid_attrs), 0);
  408. invalid_attrs = valid_attrs;
  409. invalid_attrs.min_nr_regions = 1;
  410. KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
  411. invalid_attrs = valid_attrs;
  412. invalid_attrs.max_nr_regions = 9;
  413. KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
  414. invalid_attrs = valid_attrs;
  415. invalid_attrs.aggr_interval = 4999;
  416. KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
  417. damon_destroy_ctx(c);
  418. }
  419. static void damon_test_moving_sum(struct kunit *test)
  420. {
  421. unsigned int mvsum = 50000, nomvsum = 50000, len_window = 10;
  422. unsigned int new_values[] = {10000, 0, 10000, 0, 0, 0, 10000, 0, 0, 0};
  423. unsigned int expects[] = {55000, 50000, 55000, 50000, 45000, 40000,
  424. 45000, 40000, 35000, 30000};
  425. int i;
  426. for (i = 0; i < ARRAY_SIZE(new_values); i++) {
  427. mvsum = damon_moving_sum(mvsum, nomvsum, len_window,
  428. new_values[i]);
  429. KUNIT_EXPECT_EQ(test, mvsum, expects[i]);
  430. }
  431. }
  432. static void damos_test_new_filter(struct kunit *test)
  433. {
  434. struct damos_filter *filter;
  435. filter = damos_new_filter(DAMOS_FILTER_TYPE_ANON, true, false);
  436. if (!filter)
  437. kunit_skip(test, "filter alloc fail");
  438. KUNIT_EXPECT_EQ(test, filter->type, DAMOS_FILTER_TYPE_ANON);
  439. KUNIT_EXPECT_EQ(test, filter->matching, true);
  440. KUNIT_EXPECT_PTR_EQ(test, filter->list.prev, &filter->list);
  441. KUNIT_EXPECT_PTR_EQ(test, filter->list.next, &filter->list);
  442. damos_destroy_filter(filter);
  443. }
  444. static void damos_test_commit_quota_goal_for(struct kunit *test,
  445. struct damos_quota_goal *dst,
  446. struct damos_quota_goal *src)
  447. {
  448. u64 dst_last_psi_total = 0;
  449. if (dst->metric == DAMOS_QUOTA_SOME_MEM_PSI_US)
  450. dst_last_psi_total = dst->last_psi_total;
  451. damos_commit_quota_goal(dst, src);
  452. KUNIT_EXPECT_EQ(test, dst->metric, src->metric);
  453. KUNIT_EXPECT_EQ(test, dst->target_value, src->target_value);
  454. if (src->metric == DAMOS_QUOTA_USER_INPUT)
  455. KUNIT_EXPECT_EQ(test, dst->current_value, src->current_value);
  456. if (dst_last_psi_total && src->metric == DAMOS_QUOTA_SOME_MEM_PSI_US)
  457. KUNIT_EXPECT_EQ(test, dst->last_psi_total, dst_last_psi_total);
  458. switch (dst->metric) {
  459. case DAMOS_QUOTA_NODE_MEM_USED_BP:
  460. case DAMOS_QUOTA_NODE_MEM_FREE_BP:
  461. KUNIT_EXPECT_EQ(test, dst->nid, src->nid);
  462. break;
  463. case DAMOS_QUOTA_NODE_MEMCG_USED_BP:
  464. case DAMOS_QUOTA_NODE_MEMCG_FREE_BP:
  465. KUNIT_EXPECT_EQ(test, dst->nid, src->nid);
  466. KUNIT_EXPECT_EQ(test, dst->memcg_id, src->memcg_id);
  467. break;
  468. default:
  469. break;
  470. }
  471. }
  472. static void damos_test_commit_quota_goal(struct kunit *test)
  473. {
  474. struct damos_quota_goal dst = {
  475. .metric = DAMOS_QUOTA_SOME_MEM_PSI_US,
  476. .target_value = 1000,
  477. .current_value = 123,
  478. .last_psi_total = 456,
  479. };
  480. damos_test_commit_quota_goal_for(test, &dst,
  481. &(struct damos_quota_goal){
  482. .metric = DAMOS_QUOTA_USER_INPUT,
  483. .target_value = 789,
  484. .current_value = 12});
  485. damos_test_commit_quota_goal_for(test, &dst,
  486. &(struct damos_quota_goal){
  487. .metric = DAMOS_QUOTA_NODE_MEM_FREE_BP,
  488. .target_value = 345,
  489. .current_value = 678,
  490. .nid = 9,
  491. });
  492. damos_test_commit_quota_goal_for(test, &dst,
  493. &(struct damos_quota_goal){
  494. .metric = DAMOS_QUOTA_NODE_MEM_USED_BP,
  495. .target_value = 12,
  496. .current_value = 345,
  497. .nid = 6,
  498. });
  499. damos_test_commit_quota_goal_for(test, &dst,
  500. &(struct damos_quota_goal){
  501. .metric = DAMOS_QUOTA_NODE_MEMCG_USED_BP,
  502. .target_value = 456,
  503. .current_value = 567,
  504. .nid = 6,
  505. .memcg_id = 7,
  506. });
  507. damos_test_commit_quota_goal_for(test, &dst,
  508. &(struct damos_quota_goal){
  509. .metric = DAMOS_QUOTA_NODE_MEMCG_FREE_BP,
  510. .target_value = 890,
  511. .current_value = 901,
  512. .nid = 10,
  513. .memcg_id = 1,
  514. });
  515. damos_test_commit_quota_goal_for(test, &dst,
  516. &(struct damos_quota_goal) {
  517. .metric = DAMOS_QUOTA_SOME_MEM_PSI_US,
  518. .target_value = 234,
  519. .current_value = 345,
  520. .last_psi_total = 567,
  521. });
  522. }
  523. static void damos_test_commit_quota_goals_for(struct kunit *test,
  524. struct damos_quota_goal *dst_goals, int nr_dst_goals,
  525. struct damos_quota_goal *src_goals, int nr_src_goals)
  526. {
  527. struct damos_quota dst, src;
  528. struct damos_quota_goal *goal, *next;
  529. bool skip = true;
  530. int i;
  531. INIT_LIST_HEAD(&dst.goals);
  532. INIT_LIST_HEAD(&src.goals);
  533. for (i = 0; i < nr_dst_goals; i++) {
  534. /*
  535. * When nr_src_goals is smaller than dst_goals,
  536. * damos_commit_quota_goals() will kfree() the dst goals.
  537. * Make it kfree()-able.
  538. */
  539. goal = damos_new_quota_goal(dst_goals[i].metric,
  540. dst_goals[i].target_value);
  541. if (!goal)
  542. goto out;
  543. damos_add_quota_goal(&dst, goal);
  544. }
  545. skip = false;
  546. for (i = 0; i < nr_src_goals; i++)
  547. damos_add_quota_goal(&src, &src_goals[i]);
  548. damos_commit_quota_goals(&dst, &src);
  549. i = 0;
  550. damos_for_each_quota_goal(goal, (&dst)) {
  551. KUNIT_EXPECT_EQ(test, goal->metric, src_goals[i].metric);
  552. KUNIT_EXPECT_EQ(test, goal->target_value,
  553. src_goals[i++].target_value);
  554. }
  555. KUNIT_EXPECT_EQ(test, i, nr_src_goals);
  556. out:
  557. damos_for_each_quota_goal_safe(goal, next, (&dst))
  558. damos_destroy_quota_goal(goal);
  559. if (skip)
  560. kunit_skip(test, "goal alloc fail");
  561. }
  562. static void damos_test_commit_quota_goals(struct kunit *test)
  563. {
  564. damos_test_commit_quota_goals_for(test,
  565. (struct damos_quota_goal[]){}, 0,
  566. (struct damos_quota_goal[]){
  567. {
  568. .metric = DAMOS_QUOTA_USER_INPUT,
  569. .target_value = 123,
  570. },
  571. }, 1);
  572. damos_test_commit_quota_goals_for(test,
  573. (struct damos_quota_goal[]){
  574. {
  575. .metric = DAMOS_QUOTA_USER_INPUT,
  576. .target_value = 234,
  577. },
  578. }, 1,
  579. (struct damos_quota_goal[]){
  580. {
  581. .metric = DAMOS_QUOTA_USER_INPUT,
  582. .target_value = 345,
  583. },
  584. }, 1);
  585. damos_test_commit_quota_goals_for(test,
  586. (struct damos_quota_goal[]){
  587. {
  588. .metric = DAMOS_QUOTA_USER_INPUT,
  589. .target_value = 456,
  590. },
  591. }, 1,
  592. (struct damos_quota_goal[]){}, 0);
  593. }
  594. static void damos_test_commit_quota(struct kunit *test)
  595. {
  596. struct damos_quota dst = {
  597. .reset_interval = 1,
  598. .ms = 2,
  599. .sz = 3,
  600. .weight_sz = 4,
  601. .weight_nr_accesses = 5,
  602. .weight_age = 6,
  603. };
  604. struct damos_quota src = {
  605. .reset_interval = 7,
  606. .ms = 8,
  607. .sz = 9,
  608. .weight_sz = 10,
  609. .weight_nr_accesses = 11,
  610. .weight_age = 12,
  611. };
  612. INIT_LIST_HEAD(&dst.goals);
  613. INIT_LIST_HEAD(&src.goals);
  614. damos_commit_quota(&dst, &src);
  615. KUNIT_EXPECT_EQ(test, dst.reset_interval, src.reset_interval);
  616. KUNIT_EXPECT_EQ(test, dst.ms, src.ms);
  617. KUNIT_EXPECT_EQ(test, dst.sz, src.sz);
  618. KUNIT_EXPECT_EQ(test, dst.weight_sz, src.weight_sz);
  619. KUNIT_EXPECT_EQ(test, dst.weight_nr_accesses, src.weight_nr_accesses);
  620. KUNIT_EXPECT_EQ(test, dst.weight_age, src.weight_age);
  621. }
  622. static int damos_test_help_dests_setup(struct damos_migrate_dests *dests,
  623. unsigned int *node_id_arr, unsigned int *weight_arr,
  624. size_t nr_dests)
  625. {
  626. size_t i;
  627. dests->node_id_arr = kmalloc_objs(*dests->node_id_arr, nr_dests);
  628. if (!dests->node_id_arr)
  629. return -ENOMEM;
  630. dests->weight_arr = kmalloc_objs(*dests->weight_arr, nr_dests);
  631. if (!dests->weight_arr) {
  632. kfree(dests->node_id_arr);
  633. dests->node_id_arr = NULL;
  634. return -ENOMEM;
  635. }
  636. for (i = 0; i < nr_dests; i++) {
  637. dests->node_id_arr[i] = node_id_arr[i];
  638. dests->weight_arr[i] = weight_arr[i];
  639. }
  640. dests->nr_dests = nr_dests;
  641. return 0;
  642. }
  643. static void damos_test_help_dests_free(struct damos_migrate_dests *dests)
  644. {
  645. kfree(dests->node_id_arr);
  646. kfree(dests->weight_arr);
  647. }
  648. static void damos_test_commit_dests_for(struct kunit *test,
  649. unsigned int *dst_node_id_arr, unsigned int *dst_weight_arr,
  650. size_t dst_nr_dests,
  651. unsigned int *src_node_id_arr, unsigned int *src_weight_arr,
  652. size_t src_nr_dests)
  653. {
  654. struct damos_migrate_dests dst = {}, src = {};
  655. int i, err;
  656. bool skip = true;
  657. err = damos_test_help_dests_setup(&dst, dst_node_id_arr,
  658. dst_weight_arr, dst_nr_dests);
  659. if (err)
  660. kunit_skip(test, "dests setup fail");
  661. err = damos_test_help_dests_setup(&src, src_node_id_arr,
  662. src_weight_arr, src_nr_dests);
  663. if (err) {
  664. damos_test_help_dests_free(&dst);
  665. kunit_skip(test, "src setup fail");
  666. }
  667. err = damos_commit_dests(&dst, &src);
  668. if (err)
  669. goto out;
  670. skip = false;
  671. KUNIT_EXPECT_EQ(test, dst.nr_dests, src_nr_dests);
  672. for (i = 0; i < dst.nr_dests; i++) {
  673. KUNIT_EXPECT_EQ(test, dst.node_id_arr[i], src_node_id_arr[i]);
  674. KUNIT_EXPECT_EQ(test, dst.weight_arr[i], src_weight_arr[i]);
  675. }
  676. out:
  677. damos_test_help_dests_free(&dst);
  678. damos_test_help_dests_free(&src);
  679. if (skip)
  680. kunit_skip(test, "skip");
  681. }
  682. static void damos_test_commit_dests(struct kunit *test)
  683. {
  684. damos_test_commit_dests_for(test,
  685. (unsigned int[]){1, 2, 3}, (unsigned int[]){2, 3, 4},
  686. 3,
  687. (unsigned int[]){4, 5, 6}, (unsigned int[]){5, 6, 7},
  688. 3);
  689. damos_test_commit_dests_for(test,
  690. (unsigned int[]){1, 2}, (unsigned int[]){2, 3},
  691. 2,
  692. (unsigned int[]){4, 5, 6}, (unsigned int[]){5, 6, 7},
  693. 3);
  694. damos_test_commit_dests_for(test,
  695. NULL, NULL, 0,
  696. (unsigned int[]){4, 5, 6}, (unsigned int[]){5, 6, 7},
  697. 3);
  698. damos_test_commit_dests_for(test,
  699. (unsigned int[]){1, 2, 3}, (unsigned int[]){2, 3, 4},
  700. 3,
  701. (unsigned int[]){4, 5}, (unsigned int[]){5, 6}, 2);
  702. damos_test_commit_dests_for(test,
  703. (unsigned int[]){1, 2, 3}, (unsigned int[]){2, 3, 4},
  704. 3,
  705. NULL, NULL, 0);
  706. }
  707. static void damos_test_commit_filter_for(struct kunit *test,
  708. struct damos_filter *dst, struct damos_filter *src)
  709. {
  710. damos_commit_filter(dst, src);
  711. KUNIT_EXPECT_EQ(test, dst->type, src->type);
  712. KUNIT_EXPECT_EQ(test, dst->matching, src->matching);
  713. KUNIT_EXPECT_EQ(test, dst->allow, src->allow);
  714. switch (src->type) {
  715. case DAMOS_FILTER_TYPE_MEMCG:
  716. KUNIT_EXPECT_EQ(test, dst->memcg_id, src->memcg_id);
  717. break;
  718. case DAMOS_FILTER_TYPE_ADDR:
  719. KUNIT_EXPECT_EQ(test, dst->addr_range.start,
  720. src->addr_range.start);
  721. KUNIT_EXPECT_EQ(test, dst->addr_range.end,
  722. src->addr_range.end);
  723. break;
  724. case DAMOS_FILTER_TYPE_TARGET:
  725. KUNIT_EXPECT_EQ(test, dst->target_idx, src->target_idx);
  726. break;
  727. case DAMOS_FILTER_TYPE_HUGEPAGE_SIZE:
  728. KUNIT_EXPECT_EQ(test, dst->sz_range.min, src->sz_range.min);
  729. KUNIT_EXPECT_EQ(test, dst->sz_range.max, src->sz_range.max);
  730. break;
  731. default:
  732. break;
  733. }
  734. }
  735. static void damos_test_commit_filter(struct kunit *test)
  736. {
  737. struct damos_filter dst = {
  738. .type = DAMOS_FILTER_TYPE_ACTIVE,
  739. .matching = false,
  740. .allow = false,
  741. };
  742. damos_test_commit_filter_for(test, &dst,
  743. &(struct damos_filter){
  744. .type = DAMOS_FILTER_TYPE_ANON,
  745. .matching = true,
  746. .allow = true,
  747. });
  748. damos_test_commit_filter_for(test, &dst,
  749. &(struct damos_filter){
  750. .type = DAMOS_FILTER_TYPE_MEMCG,
  751. .matching = false,
  752. .allow = false,
  753. .memcg_id = 123,
  754. });
  755. damos_test_commit_filter_for(test, &dst,
  756. &(struct damos_filter){
  757. .type = DAMOS_FILTER_TYPE_YOUNG,
  758. .matching = true,
  759. .allow = true,
  760. });
  761. damos_test_commit_filter_for(test, &dst,
  762. &(struct damos_filter){
  763. .type = DAMOS_FILTER_TYPE_HUGEPAGE_SIZE,
  764. .matching = false,
  765. .allow = false,
  766. .sz_range = {.min = 234, .max = 345},
  767. });
  768. damos_test_commit_filter_for(test, &dst,
  769. &(struct damos_filter){
  770. .type = DAMOS_FILTER_TYPE_UNMAPPED,
  771. .matching = true,
  772. .allow = true,
  773. });
  774. damos_test_commit_filter_for(test, &dst,
  775. &(struct damos_filter){
  776. .type = DAMOS_FILTER_TYPE_ADDR,
  777. .matching = false,
  778. .allow = false,
  779. .addr_range = {.start = 456, .end = 567},
  780. });
  781. damos_test_commit_filter_for(test, &dst,
  782. &(struct damos_filter){
  783. .type = DAMOS_FILTER_TYPE_TARGET,
  784. .matching = true,
  785. .allow = true,
  786. .target_idx = 6,
  787. });
  788. }
  789. static void damos_test_help_initailize_scheme(struct damos *scheme)
  790. {
  791. INIT_LIST_HEAD(&scheme->quota.goals);
  792. INIT_LIST_HEAD(&scheme->core_filters);
  793. INIT_LIST_HEAD(&scheme->ops_filters);
  794. }
  795. static void damos_test_commit_for(struct kunit *test, struct damos *dst,
  796. struct damos *src)
  797. {
  798. int err;
  799. damos_test_help_initailize_scheme(dst);
  800. damos_test_help_initailize_scheme(src);
  801. err = damos_commit(dst, src);
  802. if (err)
  803. kunit_skip(test, "damos_commit fail");
  804. KUNIT_EXPECT_EQ(test, dst->pattern.min_sz_region,
  805. src->pattern.min_sz_region);
  806. KUNIT_EXPECT_EQ(test, dst->pattern.max_sz_region,
  807. src->pattern.max_sz_region);
  808. KUNIT_EXPECT_EQ(test, dst->pattern.min_nr_accesses,
  809. src->pattern.min_nr_accesses);
  810. KUNIT_EXPECT_EQ(test, dst->pattern.max_nr_accesses,
  811. src->pattern.max_nr_accesses);
  812. KUNIT_EXPECT_EQ(test, dst->pattern.min_age_region,
  813. src->pattern.min_age_region);
  814. KUNIT_EXPECT_EQ(test, dst->pattern.max_age_region,
  815. src->pattern.max_age_region);
  816. KUNIT_EXPECT_EQ(test, dst->action, src->action);
  817. KUNIT_EXPECT_EQ(test, dst->apply_interval_us, src->apply_interval_us);
  818. KUNIT_EXPECT_EQ(test, dst->wmarks.metric, src->wmarks.metric);
  819. KUNIT_EXPECT_EQ(test, dst->wmarks.interval, src->wmarks.interval);
  820. KUNIT_EXPECT_EQ(test, dst->wmarks.high, src->wmarks.high);
  821. KUNIT_EXPECT_EQ(test, dst->wmarks.mid, src->wmarks.mid);
  822. KUNIT_EXPECT_EQ(test, dst->wmarks.low, src->wmarks.low);
  823. switch (src->action) {
  824. case DAMOS_MIGRATE_COLD:
  825. case DAMOS_MIGRATE_HOT:
  826. KUNIT_EXPECT_EQ(test, dst->target_nid, src->target_nid);
  827. break;
  828. default:
  829. break;
  830. }
  831. }
  832. static void damos_test_commit_pageout(struct kunit *test)
  833. {
  834. damos_test_commit_for(test,
  835. &(struct damos){
  836. .pattern = (struct damos_access_pattern){
  837. 1, 2, 3, 4, 5, 6},
  838. .action = DAMOS_PAGEOUT,
  839. .apply_interval_us = 1000000,
  840. .wmarks = (struct damos_watermarks){
  841. DAMOS_WMARK_FREE_MEM_RATE,
  842. 900, 100, 50},
  843. },
  844. &(struct damos){
  845. .pattern = (struct damos_access_pattern){
  846. 2, 3, 4, 5, 6, 7},
  847. .action = DAMOS_PAGEOUT,
  848. .apply_interval_us = 2000000,
  849. .wmarks = (struct damos_watermarks){
  850. DAMOS_WMARK_FREE_MEM_RATE,
  851. 800, 50, 30},
  852. });
  853. }
  854. static void damos_test_commit_migrate_hot(struct kunit *test)
  855. {
  856. damos_test_commit_for(test,
  857. &(struct damos){
  858. .pattern = (struct damos_access_pattern){
  859. 1, 2, 3, 4, 5, 6},
  860. .action = DAMOS_PAGEOUT,
  861. .apply_interval_us = 1000000,
  862. .wmarks = (struct damos_watermarks){
  863. DAMOS_WMARK_FREE_MEM_RATE,
  864. 900, 100, 50},
  865. },
  866. &(struct damos){
  867. .pattern = (struct damos_access_pattern){
  868. 2, 3, 4, 5, 6, 7},
  869. .action = DAMOS_MIGRATE_HOT,
  870. .apply_interval_us = 2000000,
  871. .target_nid = 5,
  872. });
  873. }
  874. static struct damon_target *damon_test_help_setup_target(
  875. unsigned long region_start_end[][2], int nr_regions)
  876. {
  877. struct damon_target *t;
  878. struct damon_region *r;
  879. int i;
  880. t = damon_new_target();
  881. if (!t)
  882. return NULL;
  883. for (i = 0; i < nr_regions; i++) {
  884. r = damon_new_region(region_start_end[i][0],
  885. region_start_end[i][1]);
  886. if (!r) {
  887. damon_free_target(t);
  888. return NULL;
  889. }
  890. damon_add_region(r, t);
  891. }
  892. return t;
  893. }
  894. static void damon_test_commit_target_regions_for(struct kunit *test,
  895. unsigned long dst_start_end[][2], int nr_dst_regions,
  896. unsigned long src_start_end[][2], int nr_src_regions,
  897. unsigned long expect_start_end[][2], int nr_expect_regions)
  898. {
  899. struct damon_target *dst_target, *src_target;
  900. struct damon_region *r;
  901. int i;
  902. dst_target = damon_test_help_setup_target(dst_start_end, nr_dst_regions);
  903. if (!dst_target)
  904. kunit_skip(test, "dst target setup fail");
  905. src_target = damon_test_help_setup_target(src_start_end, nr_src_regions);
  906. if (!src_target) {
  907. damon_free_target(dst_target);
  908. kunit_skip(test, "src target setup fail");
  909. }
  910. damon_commit_target_regions(dst_target, src_target, 1);
  911. i = 0;
  912. damon_for_each_region(r, dst_target) {
  913. KUNIT_EXPECT_EQ(test, r->ar.start, expect_start_end[i][0]);
  914. KUNIT_EXPECT_EQ(test, r->ar.end, expect_start_end[i][1]);
  915. i++;
  916. }
  917. KUNIT_EXPECT_EQ(test, damon_nr_regions(dst_target), nr_expect_regions);
  918. KUNIT_EXPECT_EQ(test, i, nr_expect_regions);
  919. damon_free_target(dst_target);
  920. damon_free_target(src_target);
  921. }
  922. static void damon_test_commit_target_regions(struct kunit *test)
  923. {
  924. damon_test_commit_target_regions_for(test,
  925. (unsigned long[][2]) {{3, 8}, {8, 10}}, 2,
  926. (unsigned long[][2]) {{4, 6}}, 1,
  927. (unsigned long[][2]) {{4, 6}}, 1);
  928. damon_test_commit_target_regions_for(test,
  929. (unsigned long[][2]) {{3, 8}, {8, 10}}, 2,
  930. (unsigned long[][2]) {}, 0,
  931. (unsigned long[][2]) {{3, 8}, {8, 10}}, 2);
  932. }
  933. static void damos_test_filter_out(struct kunit *test)
  934. {
  935. struct damon_target *t;
  936. struct damon_region *r, *r2;
  937. struct damos_filter *f;
  938. f = damos_new_filter(DAMOS_FILTER_TYPE_ADDR, true, false);
  939. if (!f)
  940. kunit_skip(test, "filter alloc fail");
  941. f->addr_range = (struct damon_addr_range){.start = 2, .end = 6};
  942. t = damon_new_target();
  943. if (!t) {
  944. damos_destroy_filter(f);
  945. kunit_skip(test, "target alloc fail");
  946. }
  947. r = damon_new_region(3, 5);
  948. if (!r) {
  949. damos_destroy_filter(f);
  950. damon_free_target(t);
  951. kunit_skip(test, "region alloc fail");
  952. }
  953. damon_add_region(r, t);
  954. /* region in the range */
  955. KUNIT_EXPECT_TRUE(test, damos_filter_match(NULL, t, r, f, 1));
  956. KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
  957. /* region before the range */
  958. r->ar.start = 1;
  959. r->ar.end = 2;
  960. KUNIT_EXPECT_FALSE(test,
  961. damos_filter_match(NULL, t, r, f, 1));
  962. KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
  963. /* region after the range */
  964. r->ar.start = 6;
  965. r->ar.end = 8;
  966. KUNIT_EXPECT_FALSE(test,
  967. damos_filter_match(NULL, t, r, f, 1));
  968. KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 1);
  969. /* region started before the range */
  970. r->ar.start = 1;
  971. r->ar.end = 4;
  972. KUNIT_EXPECT_FALSE(test, damos_filter_match(NULL, t, r, f, 1));
  973. /* filter should have split the region */
  974. KUNIT_EXPECT_EQ(test, r->ar.start, 1);
  975. KUNIT_EXPECT_EQ(test, r->ar.end, 2);
  976. KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
  977. r2 = damon_next_region(r);
  978. KUNIT_EXPECT_EQ(test, r2->ar.start, 2);
  979. KUNIT_EXPECT_EQ(test, r2->ar.end, 4);
  980. damon_destroy_region(r2, t);
  981. /* region started in the range */
  982. r->ar.start = 2;
  983. r->ar.end = 8;
  984. KUNIT_EXPECT_TRUE(test,
  985. damos_filter_match(NULL, t, r, f, 1));
  986. /* filter should have split the region */
  987. KUNIT_EXPECT_EQ(test, r->ar.start, 2);
  988. KUNIT_EXPECT_EQ(test, r->ar.end, 6);
  989. KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
  990. r2 = damon_next_region(r);
  991. KUNIT_EXPECT_EQ(test, r2->ar.start, 6);
  992. KUNIT_EXPECT_EQ(test, r2->ar.end, 8);
  993. damon_destroy_region(r2, t);
  994. damon_free_target(t);
  995. damos_free_filter(f);
  996. }
  997. static void damon_test_feed_loop_next_input(struct kunit *test)
  998. {
  999. unsigned long last_input = 900000, current_score = 200;
  1000. /*
  1001. * If current score is lower than the goal, which is always 10,000
  1002. * (read the comment on damon_feed_loop_next_input()'s comment), next
  1003. * input should be higher than the last input.
  1004. */
  1005. KUNIT_EXPECT_GT(test,
  1006. damon_feed_loop_next_input(last_input, current_score),
  1007. last_input);
  1008. /*
  1009. * If current score is higher than the goal, next input should be lower
  1010. * than the last input.
  1011. */
  1012. current_score = 250000000;
  1013. KUNIT_EXPECT_LT(test,
  1014. damon_feed_loop_next_input(last_input, current_score),
  1015. last_input);
  1016. /*
  1017. * The next input depends on the distance between the current score and
  1018. * the goal
  1019. */
  1020. KUNIT_EXPECT_GT(test,
  1021. damon_feed_loop_next_input(last_input, 200),
  1022. damon_feed_loop_next_input(last_input, 2000));
  1023. }
  1024. static void damon_test_set_filters_default_reject(struct kunit *test)
  1025. {
  1026. struct damos scheme;
  1027. struct damos_filter *target_filter, *anon_filter;
  1028. INIT_LIST_HEAD(&scheme.core_filters);
  1029. INIT_LIST_HEAD(&scheme.ops_filters);
  1030. damos_set_filters_default_reject(&scheme);
  1031. /*
  1032. * No filter is installed. Allow by default on both core and ops layer
  1033. * filtering stages, since there are no filters at all.
  1034. */
  1035. KUNIT_EXPECT_EQ(test, scheme.core_filters_default_reject, false);
  1036. KUNIT_EXPECT_EQ(test, scheme.ops_filters_default_reject, false);
  1037. target_filter = damos_new_filter(DAMOS_FILTER_TYPE_TARGET, true, true);
  1038. if (!target_filter)
  1039. kunit_skip(test, "filter alloc fail");
  1040. damos_add_filter(&scheme, target_filter);
  1041. damos_set_filters_default_reject(&scheme);
  1042. /*
  1043. * A core-handled allow-filter is installed.
  1044. * Reject by default on core layer filtering stage due to the last
  1045. * core-layer-filter's behavior.
  1046. * Allow by default on ops layer filtering stage due to the absence of
  1047. * ops layer filters.
  1048. */
  1049. KUNIT_EXPECT_EQ(test, scheme.core_filters_default_reject, true);
  1050. KUNIT_EXPECT_EQ(test, scheme.ops_filters_default_reject, false);
  1051. target_filter->allow = false;
  1052. damos_set_filters_default_reject(&scheme);
  1053. /*
  1054. * A core-handled reject-filter is installed.
  1055. * Allow by default on core layer filtering stage due to the last
  1056. * core-layer-filter's behavior.
  1057. * Allow by default on ops layer filtering stage due to the absence of
  1058. * ops layer filters.
  1059. */
  1060. KUNIT_EXPECT_EQ(test, scheme.core_filters_default_reject, false);
  1061. KUNIT_EXPECT_EQ(test, scheme.ops_filters_default_reject, false);
  1062. anon_filter = damos_new_filter(DAMOS_FILTER_TYPE_ANON, true, true);
  1063. if (!anon_filter) {
  1064. damos_free_filter(target_filter);
  1065. kunit_skip(test, "anon_filter alloc fail");
  1066. }
  1067. damos_add_filter(&scheme, anon_filter);
  1068. damos_set_filters_default_reject(&scheme);
  1069. /*
  1070. * A core-handled reject-filter and ops-handled allow-filter are installed.
  1071. * Allow by default on core layer filtering stage due to the existence
  1072. * of the ops-handled filter.
  1073. * Reject by default on ops layer filtering stage due to the last
  1074. * ops-layer-filter's behavior.
  1075. */
  1076. KUNIT_EXPECT_EQ(test, scheme.core_filters_default_reject, false);
  1077. KUNIT_EXPECT_EQ(test, scheme.ops_filters_default_reject, true);
  1078. target_filter->allow = true;
  1079. damos_set_filters_default_reject(&scheme);
  1080. /*
  1081. * A core-handled allow-filter and ops-handled allow-filter are
  1082. * installed.
  1083. * Allow by default on core layer filtering stage due to the existence
  1084. * of the ops-handled filter.
  1085. * Reject by default on ops layer filtering stage due to the last
  1086. * ops-layer-filter's behavior.
  1087. */
  1088. KUNIT_EXPECT_EQ(test, scheme.core_filters_default_reject, false);
  1089. KUNIT_EXPECT_EQ(test, scheme.ops_filters_default_reject, true);
  1090. damos_free_filter(anon_filter);
  1091. damos_free_filter(target_filter);
  1092. }
  1093. static struct kunit_case damon_test_cases[] = {
  1094. KUNIT_CASE(damon_test_target),
  1095. KUNIT_CASE(damon_test_regions),
  1096. KUNIT_CASE(damon_test_aggregate),
  1097. KUNIT_CASE(damon_test_split_at),
  1098. KUNIT_CASE(damon_test_merge_two),
  1099. KUNIT_CASE(damon_test_merge_regions_of),
  1100. KUNIT_CASE(damon_test_split_regions_of),
  1101. KUNIT_CASE(damon_test_ops_registration),
  1102. KUNIT_CASE(damon_test_set_regions),
  1103. KUNIT_CASE(damon_test_nr_accesses_to_accesses_bp),
  1104. KUNIT_CASE(damon_test_update_monitoring_result),
  1105. KUNIT_CASE(damon_test_set_attrs),
  1106. KUNIT_CASE(damon_test_moving_sum),
  1107. KUNIT_CASE(damos_test_new_filter),
  1108. KUNIT_CASE(damos_test_commit_quota_goal),
  1109. KUNIT_CASE(damos_test_commit_quota_goals),
  1110. KUNIT_CASE(damos_test_commit_quota),
  1111. KUNIT_CASE(damos_test_commit_dests),
  1112. KUNIT_CASE(damos_test_commit_filter),
  1113. KUNIT_CASE(damos_test_commit_pageout),
  1114. KUNIT_CASE(damos_test_commit_migrate_hot),
  1115. KUNIT_CASE(damon_test_commit_target_regions),
  1116. KUNIT_CASE(damos_test_filter_out),
  1117. KUNIT_CASE(damon_test_feed_loop_next_input),
  1118. KUNIT_CASE(damon_test_set_filters_default_reject),
  1119. {},
  1120. };
  1121. static struct kunit_suite damon_test_suite = {
  1122. .name = "damon",
  1123. .test_cases = damon_test_cases,
  1124. };
  1125. kunit_test_suite(damon_test_suite);
  1126. #endif /* _DAMON_CORE_TEST_H */
  1127. #endif /* CONFIG_DAMON_KUNIT_TEST */