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