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