1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * DAMON sysfs Interface 4 * 5 * Copyright (c) 2022 SeongJae Park <sj@kernel.org> 6 */ 7 8 #include <linux/slab.h> 9 #include <linux/numa.h> 10 11 #include "sysfs-common.h" 12 13 /* 14 * probe directory 15 */ 16 17 struct damos_sysfs_probe { 18 struct kobject kobj; 19 unsigned char hits; 20 }; 21 22 static struct damos_sysfs_probe *damos_sysfs_probe_alloc(unsigned char hits) 23 { 24 struct damos_sysfs_probe *probe; 25 26 probe = kzalloc_obj(*probe); 27 if (!probe) 28 return NULL; 29 probe->hits = hits; 30 return probe; 31 } 32 33 static ssize_t hits_show(struct kobject *kobj, struct kobj_attribute *attr, 34 char *buf) 35 { 36 struct damos_sysfs_probe *probe = container_of(kobj, 37 struct damos_sysfs_probe, kobj); 38 39 return sysfs_emit(buf, "%hhu\n", probe->hits); 40 } 41 42 static void damos_sysfs_probe_release(struct kobject *kobj) 43 { 44 struct damos_sysfs_probe *probe = container_of(kobj, 45 struct damos_sysfs_probe, kobj); 46 47 kfree(probe); 48 } 49 50 static struct kobj_attribute damos_sysfs_probe_hits_attr = 51 __ATTR_RO_MODE(hits, 0400); 52 53 static struct attribute *damos_sysfs_probe_attrs[] = { 54 &damos_sysfs_probe_hits_attr.attr, 55 NULL, 56 }; 57 ATTRIBUTE_GROUPS(damos_sysfs_probe); 58 59 static const struct kobj_type damos_sysfs_probe_ktype = { 60 .release = damos_sysfs_probe_release, 61 .sysfs_ops = &kobj_sysfs_ops, 62 .default_groups = damos_sysfs_probe_groups, 63 }; 64 65 /* 66 * probes directory 67 */ 68 69 struct damos_sysfs_probes { 70 struct kobject kobj; 71 struct damos_sysfs_probe **probes_arr; 72 int nr; 73 }; 74 75 static struct damos_sysfs_probes *damos_sysfs_probes_alloc(void) 76 { 77 return kzalloc_obj(struct damos_sysfs_probes); 78 } 79 80 static void damos_sysfs_probes_rm_dirs(struct damos_sysfs_probes *probes) 81 { 82 struct damos_sysfs_probe **probes_arr = probes->probes_arr; 83 int i; 84 85 for (i = 0; i < probes->nr; i++) 86 kobject_put(&probes_arr[i]->kobj); 87 probes->nr = 0; 88 kfree(probes_arr); 89 probes->probes_arr = NULL; 90 } 91 92 static int damos_sysfs_probes_add_dirs(struct damos_sysfs_probes *probes, 93 struct damon_ctx *ctx, struct damon_region *region) 94 { 95 struct damon_probe *probe; 96 struct damos_sysfs_probe **probes_arr; 97 int i = 0; 98 99 damon_for_each_probe(probe, ctx) 100 i++; 101 102 if (!i) 103 return 0; 104 105 probes_arr = kmalloc_objs(*probes_arr, i); 106 if (!probes_arr) 107 return -ENOMEM; 108 probes->probes_arr = probes_arr; 109 110 i = 0; 111 damon_for_each_probe(probe, ctx) { 112 struct damos_sysfs_probe *sys_probe; 113 int err; 114 115 sys_probe = damos_sysfs_probe_alloc(region->probe_hits[i]); 116 if (!sys_probe) { 117 damos_sysfs_probes_rm_dirs(probes); 118 return -ENOMEM; 119 } 120 err = kobject_init_and_add(&sys_probe->kobj, 121 &damos_sysfs_probe_ktype, &probes->kobj, "%d", 122 i); 123 if (err) { 124 kobject_put(&sys_probe->kobj); 125 damos_sysfs_probes_rm_dirs(probes); 126 return err; 127 } 128 probes_arr[i++] = sys_probe; 129 probes->nr++; 130 } 131 return 0; 132 } 133 134 static void damos_sysfs_probes_release(struct kobject *kobj) 135 { 136 struct damos_sysfs_probes *probes = container_of(kobj, 137 struct damos_sysfs_probes, kobj); 138 139 kfree(probes); 140 } 141 142 static const struct kobj_type damos_sysfs_probes_ktype = { 143 .release = damos_sysfs_probes_release, 144 .sysfs_ops = &kobj_sysfs_ops, 145 }; 146 147 /* 148 * scheme region directory 149 */ 150 151 struct damon_sysfs_scheme_region { 152 struct kobject kobj; 153 struct damon_addr_range ar; 154 unsigned int nr_accesses; 155 unsigned int age; 156 unsigned long sz_filter_passed; 157 struct damos_sysfs_probes *probes; 158 struct list_head list; 159 }; 160 161 static struct damon_sysfs_scheme_region *damon_sysfs_scheme_region_alloc( 162 struct damon_region *region) 163 { 164 struct damon_sysfs_scheme_region *sysfs_region = kmalloc_obj(*sysfs_region); 165 166 if (!sysfs_region) 167 return NULL; 168 sysfs_region->kobj = (struct kobject){}; 169 sysfs_region->ar = region->ar; 170 sysfs_region->nr_accesses = region->nr_accesses_bp / 10000; 171 sysfs_region->age = region->age; 172 sysfs_region->probes = NULL; 173 INIT_LIST_HEAD(&sysfs_region->list); 174 return sysfs_region; 175 } 176 177 static int damos_sysfs_region_add_dirs( 178 struct damon_sysfs_scheme_region *region, 179 struct damon_ctx *ctx, 180 struct damon_region *dregion) 181 { 182 struct damos_sysfs_probes *probes = damos_sysfs_probes_alloc(); 183 int err; 184 185 if (!probes) 186 return -ENOMEM; 187 err = kobject_init_and_add(&probes->kobj, &damos_sysfs_probes_ktype, 188 ®ion->kobj, "probes"); 189 if (err) 190 goto fail; 191 err = damos_sysfs_probes_add_dirs(probes, ctx, dregion); 192 if (err) 193 goto fail; 194 195 region->probes = probes; 196 return 0; 197 198 fail: 199 kobject_put(&probes->kobj); 200 return err; 201 } 202 203 static void damos_sysfs_region_rm_dirs( 204 struct damon_sysfs_scheme_region *region) 205 { 206 damos_sysfs_probes_rm_dirs(region->probes); 207 kobject_put(®ion->probes->kobj); 208 } 209 210 static ssize_t start_show(struct kobject *kobj, struct kobj_attribute *attr, 211 char *buf) 212 { 213 struct damon_sysfs_scheme_region *region = container_of(kobj, 214 struct damon_sysfs_scheme_region, kobj); 215 216 return sysfs_emit(buf, "%lu\n", region->ar.start); 217 } 218 219 static ssize_t end_show(struct kobject *kobj, struct kobj_attribute *attr, 220 char *buf) 221 { 222 struct damon_sysfs_scheme_region *region = container_of(kobj, 223 struct damon_sysfs_scheme_region, kobj); 224 225 return sysfs_emit(buf, "%lu\n", region->ar.end); 226 } 227 228 static ssize_t nr_accesses_show(struct kobject *kobj, 229 struct kobj_attribute *attr, char *buf) 230 { 231 struct damon_sysfs_scheme_region *region = container_of(kobj, 232 struct damon_sysfs_scheme_region, kobj); 233 234 return sysfs_emit(buf, "%u\n", region->nr_accesses); 235 } 236 237 static ssize_t age_show(struct kobject *kobj, struct kobj_attribute *attr, 238 char *buf) 239 { 240 struct damon_sysfs_scheme_region *region = container_of(kobj, 241 struct damon_sysfs_scheme_region, kobj); 242 243 return sysfs_emit(buf, "%u\n", region->age); 244 } 245 246 static ssize_t sz_filter_passed_show(struct kobject *kobj, 247 struct kobj_attribute *attr, char *buf) 248 { 249 struct damon_sysfs_scheme_region *region = container_of(kobj, 250 struct damon_sysfs_scheme_region, kobj); 251 252 return sysfs_emit(buf, "%lu\n", region->sz_filter_passed); 253 } 254 255 static void damon_sysfs_scheme_region_release(struct kobject *kobj) 256 { 257 struct damon_sysfs_scheme_region *region = container_of(kobj, 258 struct damon_sysfs_scheme_region, kobj); 259 260 kfree(region); 261 } 262 263 static struct kobj_attribute damon_sysfs_scheme_region_start_attr = 264 __ATTR_RO_MODE(start, 0400); 265 266 static struct kobj_attribute damon_sysfs_scheme_region_end_attr = 267 __ATTR_RO_MODE(end, 0400); 268 269 static struct kobj_attribute damon_sysfs_scheme_region_nr_accesses_attr = 270 __ATTR_RO_MODE(nr_accesses, 0400); 271 272 static struct kobj_attribute damon_sysfs_scheme_region_age_attr = 273 __ATTR_RO_MODE(age, 0400); 274 275 static struct kobj_attribute damon_sysfs_scheme_region_sz_filter_passed_attr = 276 __ATTR_RO_MODE(sz_filter_passed, 0400); 277 278 static struct attribute *damon_sysfs_scheme_region_attrs[] = { 279 &damon_sysfs_scheme_region_start_attr.attr, 280 &damon_sysfs_scheme_region_end_attr.attr, 281 &damon_sysfs_scheme_region_nr_accesses_attr.attr, 282 &damon_sysfs_scheme_region_age_attr.attr, 283 &damon_sysfs_scheme_region_sz_filter_passed_attr.attr, 284 NULL, 285 }; 286 ATTRIBUTE_GROUPS(damon_sysfs_scheme_region); 287 288 static const struct kobj_type damon_sysfs_scheme_region_ktype = { 289 .release = damon_sysfs_scheme_region_release, 290 .sysfs_ops = &kobj_sysfs_ops, 291 .default_groups = damon_sysfs_scheme_region_groups, 292 }; 293 294 /* 295 * scheme regions directory 296 */ 297 298 struct damon_sysfs_scheme_regions { 299 struct kobject kobj; 300 struct list_head regions_list; 301 int nr_regions; 302 unsigned long total_bytes; 303 }; 304 305 static struct damon_sysfs_scheme_regions * 306 damon_sysfs_scheme_regions_alloc(void) 307 { 308 struct damon_sysfs_scheme_regions *regions = kmalloc_obj(*regions); 309 310 if (!regions) 311 return NULL; 312 313 regions->kobj = (struct kobject){}; 314 INIT_LIST_HEAD(®ions->regions_list); 315 regions->nr_regions = 0; 316 regions->total_bytes = 0; 317 return regions; 318 } 319 320 static ssize_t total_bytes_show(struct kobject *kobj, 321 struct kobj_attribute *attr, char *buf) 322 { 323 struct damon_sysfs_scheme_regions *regions = container_of(kobj, 324 struct damon_sysfs_scheme_regions, kobj); 325 326 return sysfs_emit(buf, "%lu\n", regions->total_bytes); 327 } 328 329 static void damon_sysfs_scheme_regions_rm_dirs( 330 struct damon_sysfs_scheme_regions *regions) 331 { 332 struct damon_sysfs_scheme_region *r, *next; 333 334 list_for_each_entry_safe(r, next, ®ions->regions_list, list) { 335 damos_sysfs_region_rm_dirs(r); 336 list_del(&r->list); 337 kobject_put(&r->kobj); 338 regions->nr_regions--; 339 } 340 } 341 342 static void damon_sysfs_scheme_regions_release(struct kobject *kobj) 343 { 344 kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj)); 345 } 346 347 static struct kobj_attribute damon_sysfs_scheme_regions_total_bytes_attr = 348 __ATTR_RO_MODE(total_bytes, 0400); 349 350 static struct attribute *damon_sysfs_scheme_regions_attrs[] = { 351 &damon_sysfs_scheme_regions_total_bytes_attr.attr, 352 NULL, 353 }; 354 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions); 355 356 static const struct kobj_type damon_sysfs_scheme_regions_ktype = { 357 .release = damon_sysfs_scheme_regions_release, 358 .sysfs_ops = &kobj_sysfs_ops, 359 .default_groups = damon_sysfs_scheme_regions_groups, 360 }; 361 362 /* 363 * schemes/stats directory 364 */ 365 366 struct damon_sysfs_stats { 367 struct kobject kobj; 368 unsigned long nr_tried; 369 unsigned long sz_tried; 370 unsigned long nr_applied; 371 unsigned long sz_applied; 372 unsigned long sz_ops_filter_passed; 373 unsigned long qt_exceeds; 374 unsigned long nr_snapshots; 375 unsigned long max_nr_snapshots; 376 }; 377 378 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void) 379 { 380 return kzalloc_obj(struct damon_sysfs_stats); 381 } 382 383 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr, 384 char *buf) 385 { 386 struct damon_sysfs_stats *stats = container_of(kobj, 387 struct damon_sysfs_stats, kobj); 388 389 return sysfs_emit(buf, "%lu\n", stats->nr_tried); 390 } 391 392 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr, 393 char *buf) 394 { 395 struct damon_sysfs_stats *stats = container_of(kobj, 396 struct damon_sysfs_stats, kobj); 397 398 return sysfs_emit(buf, "%lu\n", stats->sz_tried); 399 } 400 401 static ssize_t nr_applied_show(struct kobject *kobj, 402 struct kobj_attribute *attr, char *buf) 403 { 404 struct damon_sysfs_stats *stats = container_of(kobj, 405 struct damon_sysfs_stats, kobj); 406 407 return sysfs_emit(buf, "%lu\n", stats->nr_applied); 408 } 409 410 static ssize_t sz_applied_show(struct kobject *kobj, 411 struct kobj_attribute *attr, char *buf) 412 { 413 struct damon_sysfs_stats *stats = container_of(kobj, 414 struct damon_sysfs_stats, kobj); 415 416 return sysfs_emit(buf, "%lu\n", stats->sz_applied); 417 } 418 419 static ssize_t sz_ops_filter_passed_show(struct kobject *kobj, 420 struct kobj_attribute *attr, char *buf) 421 { 422 struct damon_sysfs_stats *stats = container_of(kobj, 423 struct damon_sysfs_stats, kobj); 424 425 return sysfs_emit(buf, "%lu\n", stats->sz_ops_filter_passed); 426 } 427 428 static ssize_t qt_exceeds_show(struct kobject *kobj, 429 struct kobj_attribute *attr, char *buf) 430 { 431 struct damon_sysfs_stats *stats = container_of(kobj, 432 struct damon_sysfs_stats, kobj); 433 434 return sysfs_emit(buf, "%lu\n", stats->qt_exceeds); 435 } 436 437 static ssize_t nr_snapshots_show(struct kobject *kobj, 438 struct kobj_attribute *attr, char *buf) 439 { 440 struct damon_sysfs_stats *stats = container_of(kobj, 441 struct damon_sysfs_stats, kobj); 442 443 return sysfs_emit(buf, "%lu\n", stats->nr_snapshots); 444 } 445 446 static ssize_t max_nr_snapshots_show(struct kobject *kobj, 447 struct kobj_attribute *attr, char *buf) 448 { 449 struct damon_sysfs_stats *stats = container_of(kobj, 450 struct damon_sysfs_stats, kobj); 451 452 return sysfs_emit(buf, "%lu\n", stats->max_nr_snapshots); 453 } 454 455 static ssize_t max_nr_snapshots_store(struct kobject *kobj, 456 struct kobj_attribute *attr, const char *buf, size_t count) 457 { 458 struct damon_sysfs_stats *stats = container_of(kobj, 459 struct damon_sysfs_stats, kobj); 460 unsigned long max_nr_snapshots, err = kstrtoul(buf, 0, &max_nr_snapshots); 461 462 if (err) 463 return err; 464 stats->max_nr_snapshots = max_nr_snapshots; 465 return count; 466 } 467 468 static void damon_sysfs_stats_release(struct kobject *kobj) 469 { 470 kfree(container_of(kobj, struct damon_sysfs_stats, kobj)); 471 } 472 473 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr = 474 __ATTR_RO_MODE(nr_tried, 0400); 475 476 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr = 477 __ATTR_RO_MODE(sz_tried, 0400); 478 479 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr = 480 __ATTR_RO_MODE(nr_applied, 0400); 481 482 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr = 483 __ATTR_RO_MODE(sz_applied, 0400); 484 485 static struct kobj_attribute damon_sysfs_stats_sz_ops_filter_passed_attr = 486 __ATTR_RO_MODE(sz_ops_filter_passed, 0400); 487 488 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr = 489 __ATTR_RO_MODE(qt_exceeds, 0400); 490 491 static struct kobj_attribute damon_sysfs_stats_nr_snapshots_attr = 492 __ATTR_RO_MODE(nr_snapshots, 0400); 493 494 static struct kobj_attribute damon_sysfs_stats_max_nr_snapshots_attr = 495 __ATTR_RW_MODE(max_nr_snapshots, 0600); 496 497 static struct attribute *damon_sysfs_stats_attrs[] = { 498 &damon_sysfs_stats_nr_tried_attr.attr, 499 &damon_sysfs_stats_sz_tried_attr.attr, 500 &damon_sysfs_stats_nr_applied_attr.attr, 501 &damon_sysfs_stats_sz_applied_attr.attr, 502 &damon_sysfs_stats_sz_ops_filter_passed_attr.attr, 503 &damon_sysfs_stats_qt_exceeds_attr.attr, 504 &damon_sysfs_stats_nr_snapshots_attr.attr, 505 &damon_sysfs_stats_max_nr_snapshots_attr.attr, 506 NULL, 507 }; 508 ATTRIBUTE_GROUPS(damon_sysfs_stats); 509 510 static const struct kobj_type damon_sysfs_stats_ktype = { 511 .release = damon_sysfs_stats_release, 512 .sysfs_ops = &kobj_sysfs_ops, 513 .default_groups = damon_sysfs_stats_groups, 514 }; 515 516 /* 517 * filter directory 518 */ 519 520 /* 521 * enum damos_sysfs_filter_handle_layer - Layers handling filters of a dir. 522 */ 523 enum damos_sysfs_filter_handle_layer { 524 DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE, 525 DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS, 526 DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH, 527 }; 528 529 struct damon_sysfs_scheme_filter { 530 struct kobject kobj; 531 enum damos_sysfs_filter_handle_layer handle_layer; 532 enum damos_filter_type type; 533 bool matching; 534 bool allow; 535 char *memcg_path; 536 struct damon_addr_range addr_range; 537 struct damon_size_range sz_range; 538 int target_idx; 539 }; 540 541 static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc( 542 enum damos_sysfs_filter_handle_layer layer) 543 { 544 struct damon_sysfs_scheme_filter *filter; 545 546 filter = kzalloc_obj(struct damon_sysfs_scheme_filter); 547 if (filter) 548 filter->handle_layer = layer; 549 return filter; 550 } 551 552 struct damos_sysfs_filter_type_name { 553 enum damos_filter_type type; 554 char *name; 555 }; 556 557 static const struct damos_sysfs_filter_type_name 558 damos_sysfs_filter_type_names[] = { 559 { 560 .type = DAMOS_FILTER_TYPE_ANON, 561 .name = "anon", 562 }, 563 { 564 .type = DAMOS_FILTER_TYPE_ACTIVE, 565 .name = "active", 566 }, 567 { 568 .type = DAMOS_FILTER_TYPE_MEMCG, 569 .name = "memcg", 570 }, 571 { 572 .type = DAMOS_FILTER_TYPE_YOUNG, 573 .name = "young", 574 }, 575 { 576 .type = DAMOS_FILTER_TYPE_HUGEPAGE_SIZE, 577 .name = "hugepage_size", 578 }, 579 { 580 .type = DAMOS_FILTER_TYPE_UNMAPPED, 581 .name = "unmapped", 582 }, 583 { 584 .type = DAMOS_FILTER_TYPE_ADDR, 585 .name = "addr", 586 }, 587 { 588 .type = DAMOS_FILTER_TYPE_TARGET, 589 .name = "target", 590 }, 591 }; 592 593 static ssize_t type_show(struct kobject *kobj, 594 struct kobj_attribute *attr, char *buf) 595 { 596 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 597 struct damon_sysfs_scheme_filter, kobj); 598 int i; 599 600 for (i = 0; i < ARRAY_SIZE(damos_sysfs_filter_type_names); i++) { 601 const struct damos_sysfs_filter_type_name *type_name; 602 603 type_name = &damos_sysfs_filter_type_names[i]; 604 if (type_name->type == filter->type) 605 return sysfs_emit(buf, "%s\n", type_name->name); 606 } 607 return -EINVAL; 608 } 609 610 static bool damos_sysfs_scheme_filter_valid_type( 611 enum damos_sysfs_filter_handle_layer layer, 612 enum damos_filter_type type) 613 { 614 switch (layer) { 615 case DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH: 616 return true; 617 case DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE: 618 return !damos_filter_for_ops(type); 619 case DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS: 620 return damos_filter_for_ops(type); 621 default: 622 break; 623 } 624 return false; 625 } 626 627 static ssize_t type_store(struct kobject *kobj, 628 struct kobj_attribute *attr, const char *buf, size_t count) 629 { 630 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 631 struct damon_sysfs_scheme_filter, kobj); 632 ssize_t ret = -EINVAL; 633 int i; 634 635 for (i = 0; i < ARRAY_SIZE(damos_sysfs_filter_type_names); i++) { 636 const struct damos_sysfs_filter_type_name *type_name; 637 638 type_name = &damos_sysfs_filter_type_names[i]; 639 if (sysfs_streq(buf, type_name->name)) { 640 if (!damos_sysfs_scheme_filter_valid_type( 641 filter->handle_layer, 642 type_name->type)) 643 break; 644 filter->type = type_name->type; 645 ret = count; 646 break; 647 } 648 } 649 return ret; 650 } 651 652 static ssize_t matching_show(struct kobject *kobj, 653 struct kobj_attribute *attr, char *buf) 654 { 655 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 656 struct damon_sysfs_scheme_filter, kobj); 657 658 return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N'); 659 } 660 661 static ssize_t matching_store(struct kobject *kobj, 662 struct kobj_attribute *attr, const char *buf, size_t count) 663 { 664 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 665 struct damon_sysfs_scheme_filter, kobj); 666 bool matching; 667 int err = kstrtobool(buf, &matching); 668 669 if (err) 670 return err; 671 672 filter->matching = matching; 673 return count; 674 } 675 676 static ssize_t allow_show(struct kobject *kobj, 677 struct kobj_attribute *attr, char *buf) 678 { 679 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 680 struct damon_sysfs_scheme_filter, kobj); 681 682 return sysfs_emit(buf, "%c\n", filter->allow ? 'Y' : 'N'); 683 } 684 685 static ssize_t allow_store(struct kobject *kobj, 686 struct kobj_attribute *attr, const char *buf, size_t count) 687 { 688 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 689 struct damon_sysfs_scheme_filter, kobj); 690 bool allow; 691 int err = kstrtobool(buf, &allow); 692 693 if (err) 694 return err; 695 696 filter->allow = allow; 697 return count; 698 } 699 700 static ssize_t memcg_path_show(struct kobject *kobj, 701 struct kobj_attribute *attr, char *buf) 702 { 703 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 704 struct damon_sysfs_scheme_filter, kobj); 705 int len; 706 707 if (!mutex_trylock(&damon_sysfs_lock)) 708 return -EBUSY; 709 len = sysfs_emit(buf, "%s\n", 710 filter->memcg_path ? filter->memcg_path : ""); 711 mutex_unlock(&damon_sysfs_lock); 712 return len; 713 } 714 715 static ssize_t memcg_path_store(struct kobject *kobj, 716 struct kobj_attribute *attr, const char *buf, size_t count) 717 { 718 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 719 struct damon_sysfs_scheme_filter, kobj); 720 char *path = kmalloc_array(size_add(count, 1), sizeof(*path), 721 GFP_KERNEL); 722 723 if (!path) 724 return -ENOMEM; 725 726 strscpy(path, buf, count + 1); 727 if (!mutex_trylock(&damon_sysfs_lock)) { 728 kfree(path); 729 return -EBUSY; 730 } 731 kfree(filter->memcg_path); 732 filter->memcg_path = path; 733 mutex_unlock(&damon_sysfs_lock); 734 return count; 735 } 736 737 static ssize_t addr_start_show(struct kobject *kobj, 738 struct kobj_attribute *attr, char *buf) 739 { 740 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 741 struct damon_sysfs_scheme_filter, kobj); 742 743 return sysfs_emit(buf, "%lu\n", filter->addr_range.start); 744 } 745 746 static ssize_t addr_start_store(struct kobject *kobj, 747 struct kobj_attribute *attr, const char *buf, size_t count) 748 { 749 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 750 struct damon_sysfs_scheme_filter, kobj); 751 int err = kstrtoul(buf, 0, &filter->addr_range.start); 752 753 return err ? err : count; 754 } 755 756 static ssize_t addr_end_show(struct kobject *kobj, 757 struct kobj_attribute *attr, char *buf) 758 { 759 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 760 struct damon_sysfs_scheme_filter, kobj); 761 762 return sysfs_emit(buf, "%lu\n", filter->addr_range.end); 763 } 764 765 static ssize_t addr_end_store(struct kobject *kobj, 766 struct kobj_attribute *attr, const char *buf, size_t count) 767 { 768 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 769 struct damon_sysfs_scheme_filter, kobj); 770 int err = kstrtoul(buf, 0, &filter->addr_range.end); 771 772 return err ? err : count; 773 } 774 775 static ssize_t min_show(struct kobject *kobj, 776 struct kobj_attribute *attr, char *buf) 777 { 778 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 779 struct damon_sysfs_scheme_filter, kobj); 780 781 return sysfs_emit(buf, "%lu\n", filter->sz_range.min); 782 } 783 784 static ssize_t min_store(struct kobject *kobj, 785 struct kobj_attribute *attr, const char *buf, size_t count) 786 { 787 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 788 struct damon_sysfs_scheme_filter, kobj); 789 int err = kstrtoul(buf, 0, &filter->sz_range.min); 790 791 return err ? err : count; 792 } 793 794 static ssize_t max_show(struct kobject *kobj, 795 struct kobj_attribute *attr, char *buf) 796 { 797 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 798 struct damon_sysfs_scheme_filter, kobj); 799 800 return sysfs_emit(buf, "%lu\n", filter->sz_range.max); 801 } 802 803 static ssize_t max_store(struct kobject *kobj, 804 struct kobj_attribute *attr, const char *buf, size_t count) 805 { 806 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 807 struct damon_sysfs_scheme_filter, kobj); 808 int err = kstrtoul(buf, 0, &filter->sz_range.max); 809 810 return err ? err : count; 811 } 812 813 static ssize_t damon_target_idx_show(struct kobject *kobj, 814 struct kobj_attribute *attr, char *buf) 815 { 816 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 817 struct damon_sysfs_scheme_filter, kobj); 818 819 return sysfs_emit(buf, "%d\n", filter->target_idx); 820 } 821 822 static ssize_t damon_target_idx_store(struct kobject *kobj, 823 struct kobj_attribute *attr, const char *buf, size_t count) 824 { 825 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 826 struct damon_sysfs_scheme_filter, kobj); 827 int err = kstrtoint(buf, 0, &filter->target_idx); 828 829 return err ? err : count; 830 } 831 832 static void damon_sysfs_scheme_filter_release(struct kobject *kobj) 833 { 834 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 835 struct damon_sysfs_scheme_filter, kobj); 836 837 kfree(filter->memcg_path); 838 kfree(filter); 839 } 840 841 static struct kobj_attribute damon_sysfs_scheme_filter_type_attr = 842 __ATTR_RW_MODE(type, 0600); 843 844 static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr = 845 __ATTR_RW_MODE(matching, 0600); 846 847 static struct kobj_attribute damon_sysfs_scheme_filter_allow_attr = 848 __ATTR_RW_MODE(allow, 0600); 849 850 static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr = 851 __ATTR_RW_MODE(memcg_path, 0600); 852 853 static struct kobj_attribute damon_sysfs_scheme_filter_addr_start_attr = 854 __ATTR_RW_MODE(addr_start, 0600); 855 856 static struct kobj_attribute damon_sysfs_scheme_filter_addr_end_attr = 857 __ATTR_RW_MODE(addr_end, 0600); 858 859 static struct kobj_attribute damon_sysfs_scheme_filter_min_attr = 860 __ATTR_RW_MODE(min, 0600); 861 862 static struct kobj_attribute damon_sysfs_scheme_filter_max_attr = 863 __ATTR_RW_MODE(max, 0600); 864 865 static struct kobj_attribute damon_sysfs_scheme_filter_damon_target_idx_attr = 866 __ATTR_RW_MODE(damon_target_idx, 0600); 867 868 static struct attribute *damon_sysfs_scheme_filter_attrs[] = { 869 &damon_sysfs_scheme_filter_type_attr.attr, 870 &damon_sysfs_scheme_filter_matching_attr.attr, 871 &damon_sysfs_scheme_filter_allow_attr.attr, 872 &damon_sysfs_scheme_filter_memcg_path_attr.attr, 873 &damon_sysfs_scheme_filter_addr_start_attr.attr, 874 &damon_sysfs_scheme_filter_addr_end_attr.attr, 875 &damon_sysfs_scheme_filter_min_attr.attr, 876 &damon_sysfs_scheme_filter_max_attr.attr, 877 &damon_sysfs_scheme_filter_damon_target_idx_attr.attr, 878 NULL, 879 }; 880 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter); 881 882 static const struct kobj_type damon_sysfs_scheme_filter_ktype = { 883 .release = damon_sysfs_scheme_filter_release, 884 .sysfs_ops = &kobj_sysfs_ops, 885 .default_groups = damon_sysfs_scheme_filter_groups, 886 }; 887 888 /* 889 * filters directory 890 */ 891 892 struct damon_sysfs_scheme_filters { 893 struct kobject kobj; 894 enum damos_sysfs_filter_handle_layer handle_layer; 895 struct damon_sysfs_scheme_filter **filters_arr; 896 int nr; 897 }; 898 899 static struct damon_sysfs_scheme_filters * 900 damon_sysfs_scheme_filters_alloc(enum damos_sysfs_filter_handle_layer layer) 901 { 902 struct damon_sysfs_scheme_filters *filters; 903 904 filters = kzalloc_obj(struct damon_sysfs_scheme_filters); 905 if (filters) 906 filters->handle_layer = layer; 907 return filters; 908 } 909 910 static void damon_sysfs_scheme_filters_rm_dirs( 911 struct damon_sysfs_scheme_filters *filters) 912 { 913 struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr; 914 int i; 915 916 for (i = 0; i < filters->nr; i++) 917 kobject_put(&filters_arr[i]->kobj); 918 filters->nr = 0; 919 kfree(filters_arr); 920 filters->filters_arr = NULL; 921 } 922 923 static int damon_sysfs_scheme_filters_add_dirs( 924 struct damon_sysfs_scheme_filters *filters, int nr_filters) 925 { 926 struct damon_sysfs_scheme_filter **filters_arr, *filter; 927 int err, i; 928 929 damon_sysfs_scheme_filters_rm_dirs(filters); 930 if (!nr_filters) 931 return 0; 932 933 filters_arr = kmalloc_objs(*filters_arr, nr_filters, 934 GFP_KERNEL | __GFP_NOWARN); 935 if (!filters_arr) 936 return -ENOMEM; 937 filters->filters_arr = filters_arr; 938 939 for (i = 0; i < nr_filters; i++) { 940 filter = damon_sysfs_scheme_filter_alloc( 941 filters->handle_layer); 942 if (!filter) { 943 damon_sysfs_scheme_filters_rm_dirs(filters); 944 return -ENOMEM; 945 } 946 947 err = kobject_init_and_add(&filter->kobj, 948 &damon_sysfs_scheme_filter_ktype, 949 &filters->kobj, "%d", i); 950 if (err) { 951 kobject_put(&filter->kobj); 952 damon_sysfs_scheme_filters_rm_dirs(filters); 953 return err; 954 } 955 956 filters_arr[i] = filter; 957 filters->nr++; 958 } 959 return 0; 960 } 961 962 static ssize_t nr_filters_show(struct kobject *kobj, 963 struct kobj_attribute *attr, char *buf) 964 { 965 struct damon_sysfs_scheme_filters *filters = container_of(kobj, 966 struct damon_sysfs_scheme_filters, kobj); 967 968 return sysfs_emit(buf, "%d\n", filters->nr); 969 } 970 971 static ssize_t nr_filters_store(struct kobject *kobj, 972 struct kobj_attribute *attr, const char *buf, size_t count) 973 { 974 struct damon_sysfs_scheme_filters *filters; 975 int nr, err = kstrtoint(buf, 0, &nr); 976 977 if (err) 978 return err; 979 if (nr < 0) 980 return -EINVAL; 981 982 filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj); 983 984 if (!mutex_trylock(&damon_sysfs_lock)) 985 return -EBUSY; 986 err = damon_sysfs_scheme_filters_add_dirs(filters, nr); 987 mutex_unlock(&damon_sysfs_lock); 988 if (err) 989 return err; 990 991 return count; 992 } 993 994 static void damon_sysfs_scheme_filters_release(struct kobject *kobj) 995 { 996 kfree(container_of(kobj, struct damon_sysfs_scheme_filters, kobj)); 997 } 998 999 static struct kobj_attribute damon_sysfs_scheme_filters_nr_attr = 1000 __ATTR_RW_MODE(nr_filters, 0600); 1001 1002 static struct attribute *damon_sysfs_scheme_filters_attrs[] = { 1003 &damon_sysfs_scheme_filters_nr_attr.attr, 1004 NULL, 1005 }; 1006 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filters); 1007 1008 static const struct kobj_type damon_sysfs_scheme_filters_ktype = { 1009 .release = damon_sysfs_scheme_filters_release, 1010 .sysfs_ops = &kobj_sysfs_ops, 1011 .default_groups = damon_sysfs_scheme_filters_groups, 1012 }; 1013 1014 /* 1015 * watermarks directory 1016 */ 1017 1018 struct damon_sysfs_watermarks { 1019 struct kobject kobj; 1020 enum damos_wmark_metric metric; 1021 unsigned long interval_us; 1022 unsigned long high; 1023 unsigned long mid; 1024 unsigned long low; 1025 }; 1026 1027 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc( 1028 enum damos_wmark_metric metric, unsigned long interval_us, 1029 unsigned long high, unsigned long mid, unsigned long low) 1030 { 1031 struct damon_sysfs_watermarks *watermarks = kmalloc_obj(*watermarks); 1032 1033 if (!watermarks) 1034 return NULL; 1035 watermarks->kobj = (struct kobject){}; 1036 watermarks->metric = metric; 1037 watermarks->interval_us = interval_us; 1038 watermarks->high = high; 1039 watermarks->mid = mid; 1040 watermarks->low = low; 1041 return watermarks; 1042 } 1043 1044 struct damos_sysfs_wmark_metric_name { 1045 enum damos_wmark_metric metric; 1046 char *name; 1047 }; 1048 1049 static const struct damos_sysfs_wmark_metric_name 1050 damos_sysfs_wmark_metric_names[] = { 1051 { 1052 .metric = DAMOS_WMARK_NONE, 1053 .name = "none", 1054 }, 1055 { 1056 .metric = DAMOS_WMARK_FREE_MEM_RATE, 1057 .name = "free_mem_rate", 1058 }, 1059 }; 1060 1061 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr, 1062 char *buf) 1063 { 1064 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 1065 struct damon_sysfs_watermarks, kobj); 1066 int i; 1067 1068 for (i = 0; i < ARRAY_SIZE(damos_sysfs_wmark_metric_names); i++) { 1069 const struct damos_sysfs_wmark_metric_name *metric_name; 1070 1071 metric_name = &damos_sysfs_wmark_metric_names[i]; 1072 if (metric_name->metric == watermarks->metric) 1073 return sysfs_emit(buf, "%s\n", metric_name->name); 1074 } 1075 return -EINVAL; 1076 } 1077 1078 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr, 1079 const char *buf, size_t count) 1080 { 1081 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 1082 struct damon_sysfs_watermarks, kobj); 1083 int i; 1084 1085 for (i = 0; i < ARRAY_SIZE(damos_sysfs_wmark_metric_names); i++) { 1086 const struct damos_sysfs_wmark_metric_name *metric_name; 1087 1088 metric_name = &damos_sysfs_wmark_metric_names[i]; 1089 if (sysfs_streq(buf, metric_name->name)) { 1090 watermarks->metric = metric_name->metric; 1091 return count; 1092 } 1093 } 1094 return -EINVAL; 1095 } 1096 1097 static ssize_t interval_us_show(struct kobject *kobj, 1098 struct kobj_attribute *attr, char *buf) 1099 { 1100 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 1101 struct damon_sysfs_watermarks, kobj); 1102 1103 return sysfs_emit(buf, "%lu\n", watermarks->interval_us); 1104 } 1105 1106 static ssize_t interval_us_store(struct kobject *kobj, 1107 struct kobj_attribute *attr, const char *buf, size_t count) 1108 { 1109 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 1110 struct damon_sysfs_watermarks, kobj); 1111 int err = kstrtoul(buf, 0, &watermarks->interval_us); 1112 1113 return err ? err : count; 1114 } 1115 1116 static ssize_t high_show(struct kobject *kobj, 1117 struct kobj_attribute *attr, char *buf) 1118 { 1119 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 1120 struct damon_sysfs_watermarks, kobj); 1121 1122 return sysfs_emit(buf, "%lu\n", watermarks->high); 1123 } 1124 1125 static ssize_t high_store(struct kobject *kobj, 1126 struct kobj_attribute *attr, const char *buf, size_t count) 1127 { 1128 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 1129 struct damon_sysfs_watermarks, kobj); 1130 int err = kstrtoul(buf, 0, &watermarks->high); 1131 1132 return err ? err : count; 1133 } 1134 1135 static ssize_t mid_show(struct kobject *kobj, 1136 struct kobj_attribute *attr, char *buf) 1137 { 1138 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 1139 struct damon_sysfs_watermarks, kobj); 1140 1141 return sysfs_emit(buf, "%lu\n", watermarks->mid); 1142 } 1143 1144 static ssize_t mid_store(struct kobject *kobj, 1145 struct kobj_attribute *attr, const char *buf, size_t count) 1146 { 1147 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 1148 struct damon_sysfs_watermarks, kobj); 1149 int err = kstrtoul(buf, 0, &watermarks->mid); 1150 1151 return err ? err : count; 1152 } 1153 1154 static ssize_t low_show(struct kobject *kobj, 1155 struct kobj_attribute *attr, char *buf) 1156 { 1157 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 1158 struct damon_sysfs_watermarks, kobj); 1159 1160 return sysfs_emit(buf, "%lu\n", watermarks->low); 1161 } 1162 1163 static ssize_t low_store(struct kobject *kobj, 1164 struct kobj_attribute *attr, const char *buf, size_t count) 1165 { 1166 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 1167 struct damon_sysfs_watermarks, kobj); 1168 int err = kstrtoul(buf, 0, &watermarks->low); 1169 1170 return err ? err : count; 1171 } 1172 1173 static void damon_sysfs_watermarks_release(struct kobject *kobj) 1174 { 1175 kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj)); 1176 } 1177 1178 static struct kobj_attribute damon_sysfs_watermarks_metric_attr = 1179 __ATTR_RW_MODE(metric, 0600); 1180 1181 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr = 1182 __ATTR_RW_MODE(interval_us, 0600); 1183 1184 static struct kobj_attribute damon_sysfs_watermarks_high_attr = 1185 __ATTR_RW_MODE(high, 0600); 1186 1187 static struct kobj_attribute damon_sysfs_watermarks_mid_attr = 1188 __ATTR_RW_MODE(mid, 0600); 1189 1190 static struct kobj_attribute damon_sysfs_watermarks_low_attr = 1191 __ATTR_RW_MODE(low, 0600); 1192 1193 static struct attribute *damon_sysfs_watermarks_attrs[] = { 1194 &damon_sysfs_watermarks_metric_attr.attr, 1195 &damon_sysfs_watermarks_interval_us_attr.attr, 1196 &damon_sysfs_watermarks_high_attr.attr, 1197 &damon_sysfs_watermarks_mid_attr.attr, 1198 &damon_sysfs_watermarks_low_attr.attr, 1199 NULL, 1200 }; 1201 ATTRIBUTE_GROUPS(damon_sysfs_watermarks); 1202 1203 static const struct kobj_type damon_sysfs_watermarks_ktype = { 1204 .release = damon_sysfs_watermarks_release, 1205 .sysfs_ops = &kobj_sysfs_ops, 1206 .default_groups = damon_sysfs_watermarks_groups, 1207 }; 1208 1209 /* 1210 * quota goal directory 1211 */ 1212 1213 struct damos_sysfs_quota_goal { 1214 struct kobject kobj; 1215 enum damos_quota_goal_metric metric; 1216 unsigned long target_value; 1217 unsigned long current_value; 1218 int nid; 1219 char *path; 1220 }; 1221 1222 static struct damos_sysfs_quota_goal *damos_sysfs_quota_goal_alloc(void) 1223 { 1224 return kzalloc_obj(struct damos_sysfs_quota_goal); 1225 } 1226 1227 struct damos_sysfs_qgoal_metric_name { 1228 enum damos_quota_goal_metric metric; 1229 char *name; 1230 }; 1231 1232 static 1233 struct damos_sysfs_qgoal_metric_name damos_sysfs_qgoal_metric_names[] = { 1234 { 1235 .metric = DAMOS_QUOTA_USER_INPUT, 1236 .name = "user_input", 1237 }, 1238 { 1239 .metric = DAMOS_QUOTA_SOME_MEM_PSI_US, 1240 .name = "some_mem_psi_us", 1241 }, 1242 { 1243 .metric = DAMOS_QUOTA_NODE_MEM_USED_BP, 1244 .name = "node_mem_used_bp", 1245 }, 1246 { 1247 .metric = DAMOS_QUOTA_NODE_MEM_FREE_BP, 1248 .name = "node_mem_free_bp", 1249 }, 1250 { 1251 .metric = DAMOS_QUOTA_NODE_MEMCG_USED_BP, 1252 .name = "node_memcg_used_bp", 1253 }, 1254 { 1255 .metric = DAMOS_QUOTA_NODE_MEMCG_FREE_BP, 1256 .name = "node_memcg_free_bp", 1257 }, 1258 { 1259 .metric = DAMOS_QUOTA_ACTIVE_MEM_BP, 1260 .name = "active_mem_bp", 1261 }, 1262 { 1263 .metric = DAMOS_QUOTA_INACTIVE_MEM_BP, 1264 .name = "inactive_mem_bp", 1265 }, 1266 { 1267 .metric = DAMOS_QUOTA_NODE_ELIGIBLE_MEM_BP, 1268 .name = "node_eligible_mem_bp", 1269 }, 1270 }; 1271 1272 static ssize_t target_metric_show(struct kobject *kobj, 1273 struct kobj_attribute *attr, char *buf) 1274 { 1275 struct damos_sysfs_quota_goal *goal = container_of(kobj, 1276 struct damos_sysfs_quota_goal, kobj); 1277 int i; 1278 1279 for (i = 0; i < ARRAY_SIZE(damos_sysfs_qgoal_metric_names); i++) { 1280 struct damos_sysfs_qgoal_metric_name *metric_name; 1281 1282 metric_name = &damos_sysfs_qgoal_metric_names[i]; 1283 if (metric_name->metric == goal->metric) 1284 return sysfs_emit(buf, "%s\n", metric_name->name); 1285 } 1286 return -EINVAL; 1287 } 1288 1289 static ssize_t target_metric_store(struct kobject *kobj, 1290 struct kobj_attribute *attr, const char *buf, size_t count) 1291 { 1292 struct damos_sysfs_quota_goal *goal = container_of(kobj, 1293 struct damos_sysfs_quota_goal, kobj); 1294 int i; 1295 1296 for (i = 0; i < ARRAY_SIZE(damos_sysfs_qgoal_metric_names); i++) { 1297 struct damos_sysfs_qgoal_metric_name *metric_name; 1298 1299 metric_name = &damos_sysfs_qgoal_metric_names[i]; 1300 if (sysfs_streq(buf, metric_name->name)) { 1301 goal->metric = metric_name->metric; 1302 return count; 1303 } 1304 } 1305 return -EINVAL; 1306 } 1307 1308 static ssize_t target_value_show(struct kobject *kobj, 1309 struct kobj_attribute *attr, char *buf) 1310 { 1311 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1312 damos_sysfs_quota_goal, kobj); 1313 1314 return sysfs_emit(buf, "%lu\n", goal->target_value); 1315 } 1316 1317 static ssize_t target_value_store(struct kobject *kobj, 1318 struct kobj_attribute *attr, const char *buf, size_t count) 1319 { 1320 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1321 damos_sysfs_quota_goal, kobj); 1322 int err = kstrtoul(buf, 0, &goal->target_value); 1323 1324 return err ? err : count; 1325 } 1326 1327 static ssize_t current_value_show(struct kobject *kobj, 1328 struct kobj_attribute *attr, char *buf) 1329 { 1330 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1331 damos_sysfs_quota_goal, kobj); 1332 1333 return sysfs_emit(buf, "%lu\n", goal->current_value); 1334 } 1335 1336 static ssize_t current_value_store(struct kobject *kobj, 1337 struct kobj_attribute *attr, const char *buf, size_t count) 1338 { 1339 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1340 damos_sysfs_quota_goal, kobj); 1341 int err = kstrtoul(buf, 0, &goal->current_value); 1342 1343 /* feed callback should check existence of this file and read value */ 1344 return err ? err : count; 1345 } 1346 1347 static ssize_t nid_show(struct kobject *kobj, 1348 struct kobj_attribute *attr, char *buf) 1349 { 1350 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1351 damos_sysfs_quota_goal, kobj); 1352 1353 1354 return sysfs_emit(buf, "%d\n", goal->nid); 1355 } 1356 1357 static ssize_t nid_store(struct kobject *kobj, 1358 struct kobj_attribute *attr, const char *buf, size_t count) 1359 { 1360 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1361 damos_sysfs_quota_goal, kobj); 1362 int err = kstrtoint(buf, 0, &goal->nid); 1363 1364 /* feed callback should check existence of this file and read value */ 1365 return err ? err : count; 1366 } 1367 1368 static ssize_t path_show(struct kobject *kobj, 1369 struct kobj_attribute *attr, char *buf) 1370 { 1371 struct damos_sysfs_quota_goal *goal = container_of(kobj, 1372 struct damos_sysfs_quota_goal, kobj); 1373 int len; 1374 1375 if (!mutex_trylock(&damon_sysfs_lock)) 1376 return -EBUSY; 1377 len = sysfs_emit(buf, "%s\n", goal->path ? goal->path : ""); 1378 mutex_unlock(&damon_sysfs_lock); 1379 return len; 1380 } 1381 1382 static ssize_t path_store(struct kobject *kobj, 1383 struct kobj_attribute *attr, const char *buf, size_t count) 1384 { 1385 struct damos_sysfs_quota_goal *goal = container_of(kobj, 1386 struct damos_sysfs_quota_goal, kobj); 1387 char *path = kmalloc_array(size_add(count, 1), sizeof(*path), 1388 GFP_KERNEL); 1389 1390 if (!path) 1391 return -ENOMEM; 1392 1393 strscpy(path, buf, count + 1); 1394 if (!mutex_trylock(&damon_sysfs_lock)) { 1395 kfree(path); 1396 return -EBUSY; 1397 } 1398 kfree(goal->path); 1399 goal->path = path; 1400 mutex_unlock(&damon_sysfs_lock); 1401 return count; 1402 } 1403 1404 static void damos_sysfs_quota_goal_release(struct kobject *kobj) 1405 { 1406 struct damos_sysfs_quota_goal *goal = container_of(kobj, 1407 struct damos_sysfs_quota_goal, kobj); 1408 1409 kfree(goal->path); 1410 kfree(goal); 1411 } 1412 1413 static struct kobj_attribute damos_sysfs_quota_goal_target_metric_attr = 1414 __ATTR_RW_MODE(target_metric, 0600); 1415 1416 static struct kobj_attribute damos_sysfs_quota_goal_target_value_attr = 1417 __ATTR_RW_MODE(target_value, 0600); 1418 1419 static struct kobj_attribute damos_sysfs_quota_goal_current_value_attr = 1420 __ATTR_RW_MODE(current_value, 0600); 1421 1422 static struct kobj_attribute damos_sysfs_quota_goal_nid_attr = 1423 __ATTR_RW_MODE(nid, 0600); 1424 1425 static struct kobj_attribute damos_sysfs_quota_goal_path_attr = 1426 __ATTR_RW_MODE(path, 0600); 1427 1428 static struct attribute *damos_sysfs_quota_goal_attrs[] = { 1429 &damos_sysfs_quota_goal_target_metric_attr.attr, 1430 &damos_sysfs_quota_goal_target_value_attr.attr, 1431 &damos_sysfs_quota_goal_current_value_attr.attr, 1432 &damos_sysfs_quota_goal_nid_attr.attr, 1433 &damos_sysfs_quota_goal_path_attr.attr, 1434 NULL, 1435 }; 1436 ATTRIBUTE_GROUPS(damos_sysfs_quota_goal); 1437 1438 static const struct kobj_type damos_sysfs_quota_goal_ktype = { 1439 .release = damos_sysfs_quota_goal_release, 1440 .sysfs_ops = &kobj_sysfs_ops, 1441 .default_groups = damos_sysfs_quota_goal_groups, 1442 }; 1443 1444 /* 1445 * quota goals directory 1446 */ 1447 1448 struct damos_sysfs_quota_goals { 1449 struct kobject kobj; 1450 struct damos_sysfs_quota_goal **goals_arr; /* counted by nr */ 1451 int nr; 1452 }; 1453 1454 static struct damos_sysfs_quota_goals *damos_sysfs_quota_goals_alloc(void) 1455 { 1456 return kzalloc_obj(struct damos_sysfs_quota_goals); 1457 } 1458 1459 static void damos_sysfs_quota_goals_rm_dirs( 1460 struct damos_sysfs_quota_goals *goals) 1461 { 1462 struct damos_sysfs_quota_goal **goals_arr = goals->goals_arr; 1463 int i; 1464 1465 for (i = 0; i < goals->nr; i++) 1466 kobject_put(&goals_arr[i]->kobj); 1467 goals->nr = 0; 1468 kfree(goals_arr); 1469 goals->goals_arr = NULL; 1470 } 1471 1472 static int damos_sysfs_quota_goals_add_dirs( 1473 struct damos_sysfs_quota_goals *goals, int nr_goals) 1474 { 1475 struct damos_sysfs_quota_goal **goals_arr, *goal; 1476 int err, i; 1477 1478 damos_sysfs_quota_goals_rm_dirs(goals); 1479 if (!nr_goals) 1480 return 0; 1481 1482 goals_arr = kmalloc_objs(*goals_arr, nr_goals, 1483 GFP_KERNEL | __GFP_NOWARN); 1484 if (!goals_arr) 1485 return -ENOMEM; 1486 goals->goals_arr = goals_arr; 1487 1488 for (i = 0; i < nr_goals; i++) { 1489 goal = damos_sysfs_quota_goal_alloc(); 1490 if (!goal) { 1491 damos_sysfs_quota_goals_rm_dirs(goals); 1492 return -ENOMEM; 1493 } 1494 1495 err = kobject_init_and_add(&goal->kobj, 1496 &damos_sysfs_quota_goal_ktype, &goals->kobj, 1497 "%d", i); 1498 if (err) { 1499 kobject_put(&goal->kobj); 1500 damos_sysfs_quota_goals_rm_dirs(goals); 1501 return err; 1502 } 1503 1504 goals_arr[i] = goal; 1505 goals->nr++; 1506 } 1507 return 0; 1508 } 1509 1510 static ssize_t nr_goals_show(struct kobject *kobj, 1511 struct kobj_attribute *attr, char *buf) 1512 { 1513 struct damos_sysfs_quota_goals *goals = container_of(kobj, 1514 struct damos_sysfs_quota_goals, kobj); 1515 1516 return sysfs_emit(buf, "%d\n", goals->nr); 1517 } 1518 1519 static ssize_t nr_goals_store(struct kobject *kobj, 1520 struct kobj_attribute *attr, const char *buf, size_t count) 1521 { 1522 struct damos_sysfs_quota_goals *goals; 1523 int nr, err = kstrtoint(buf, 0, &nr); 1524 1525 if (err) 1526 return err; 1527 if (nr < 0) 1528 return -EINVAL; 1529 1530 goals = container_of(kobj, struct damos_sysfs_quota_goals, kobj); 1531 1532 if (!mutex_trylock(&damon_sysfs_lock)) 1533 return -EBUSY; 1534 err = damos_sysfs_quota_goals_add_dirs(goals, nr); 1535 mutex_unlock(&damon_sysfs_lock); 1536 if (err) 1537 return err; 1538 1539 return count; 1540 } 1541 1542 static void damos_sysfs_quota_goals_release(struct kobject *kobj) 1543 { 1544 kfree(container_of(kobj, struct damos_sysfs_quota_goals, kobj)); 1545 } 1546 1547 static struct kobj_attribute damos_sysfs_quota_goals_nr_attr = 1548 __ATTR_RW_MODE(nr_goals, 0600); 1549 1550 static struct attribute *damos_sysfs_quota_goals_attrs[] = { 1551 &damos_sysfs_quota_goals_nr_attr.attr, 1552 NULL, 1553 }; 1554 ATTRIBUTE_GROUPS(damos_sysfs_quota_goals); 1555 1556 static const struct kobj_type damos_sysfs_quota_goals_ktype = { 1557 .release = damos_sysfs_quota_goals_release, 1558 .sysfs_ops = &kobj_sysfs_ops, 1559 .default_groups = damos_sysfs_quota_goals_groups, 1560 }; 1561 1562 /* 1563 * scheme/weights directory 1564 */ 1565 1566 struct damon_sysfs_weights { 1567 struct kobject kobj; 1568 unsigned int sz; 1569 unsigned int nr_accesses; 1570 unsigned int age; 1571 }; 1572 1573 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz, 1574 unsigned int nr_accesses, unsigned int age) 1575 { 1576 struct damon_sysfs_weights *weights = kmalloc_obj(*weights); 1577 1578 if (!weights) 1579 return NULL; 1580 weights->kobj = (struct kobject){}; 1581 weights->sz = sz; 1582 weights->nr_accesses = nr_accesses; 1583 weights->age = age; 1584 return weights; 1585 } 1586 1587 static ssize_t sz_permil_show(struct kobject *kobj, 1588 struct kobj_attribute *attr, char *buf) 1589 { 1590 struct damon_sysfs_weights *weights = container_of(kobj, 1591 struct damon_sysfs_weights, kobj); 1592 1593 return sysfs_emit(buf, "%u\n", weights->sz); 1594 } 1595 1596 static ssize_t sz_permil_store(struct kobject *kobj, 1597 struct kobj_attribute *attr, const char *buf, size_t count) 1598 { 1599 struct damon_sysfs_weights *weights = container_of(kobj, 1600 struct damon_sysfs_weights, kobj); 1601 int err = kstrtouint(buf, 0, &weights->sz); 1602 1603 return err ? err : count; 1604 } 1605 1606 static ssize_t nr_accesses_permil_show(struct kobject *kobj, 1607 struct kobj_attribute *attr, char *buf) 1608 { 1609 struct damon_sysfs_weights *weights = container_of(kobj, 1610 struct damon_sysfs_weights, kobj); 1611 1612 return sysfs_emit(buf, "%u\n", weights->nr_accesses); 1613 } 1614 1615 static ssize_t nr_accesses_permil_store(struct kobject *kobj, 1616 struct kobj_attribute *attr, const char *buf, size_t count) 1617 { 1618 struct damon_sysfs_weights *weights = container_of(kobj, 1619 struct damon_sysfs_weights, kobj); 1620 int err = kstrtouint(buf, 0, &weights->nr_accesses); 1621 1622 return err ? err : count; 1623 } 1624 1625 static ssize_t age_permil_show(struct kobject *kobj, 1626 struct kobj_attribute *attr, char *buf) 1627 { 1628 struct damon_sysfs_weights *weights = container_of(kobj, 1629 struct damon_sysfs_weights, kobj); 1630 1631 return sysfs_emit(buf, "%u\n", weights->age); 1632 } 1633 1634 static ssize_t age_permil_store(struct kobject *kobj, 1635 struct kobj_attribute *attr, const char *buf, size_t count) 1636 { 1637 struct damon_sysfs_weights *weights = container_of(kobj, 1638 struct damon_sysfs_weights, kobj); 1639 int err = kstrtouint(buf, 0, &weights->age); 1640 1641 return err ? err : count; 1642 } 1643 1644 static void damon_sysfs_weights_release(struct kobject *kobj) 1645 { 1646 kfree(container_of(kobj, struct damon_sysfs_weights, kobj)); 1647 } 1648 1649 static struct kobj_attribute damon_sysfs_weights_sz_attr = 1650 __ATTR_RW_MODE(sz_permil, 0600); 1651 1652 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr = 1653 __ATTR_RW_MODE(nr_accesses_permil, 0600); 1654 1655 static struct kobj_attribute damon_sysfs_weights_age_attr = 1656 __ATTR_RW_MODE(age_permil, 0600); 1657 1658 static struct attribute *damon_sysfs_weights_attrs[] = { 1659 &damon_sysfs_weights_sz_attr.attr, 1660 &damon_sysfs_weights_nr_accesses_attr.attr, 1661 &damon_sysfs_weights_age_attr.attr, 1662 NULL, 1663 }; 1664 ATTRIBUTE_GROUPS(damon_sysfs_weights); 1665 1666 static const struct kobj_type damon_sysfs_weights_ktype = { 1667 .release = damon_sysfs_weights_release, 1668 .sysfs_ops = &kobj_sysfs_ops, 1669 .default_groups = damon_sysfs_weights_groups, 1670 }; 1671 1672 /* 1673 * quotas directory 1674 */ 1675 1676 struct damon_sysfs_quotas { 1677 struct kobject kobj; 1678 struct damon_sysfs_weights *weights; 1679 struct damos_sysfs_quota_goals *goals; 1680 unsigned long ms; 1681 unsigned long sz; 1682 unsigned long reset_interval_ms; 1683 unsigned long effective_sz; /* Effective size quota in bytes */ 1684 enum damos_quota_goal_tuner goal_tuner; 1685 unsigned int fail_charge_num; 1686 unsigned int fail_charge_denom; 1687 }; 1688 1689 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void) 1690 { 1691 return kzalloc_obj(struct damon_sysfs_quotas); 1692 } 1693 1694 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas) 1695 { 1696 struct damon_sysfs_weights *weights; 1697 struct damos_sysfs_quota_goals *goals; 1698 int err; 1699 1700 weights = damon_sysfs_weights_alloc(0, 0, 0); 1701 if (!weights) 1702 return -ENOMEM; 1703 1704 err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype, 1705 "as->kobj, "weights"); 1706 if (err) { 1707 kobject_put(&weights->kobj); 1708 return err; 1709 } 1710 quotas->weights = weights; 1711 1712 goals = damos_sysfs_quota_goals_alloc(); 1713 if (!goals) { 1714 kobject_put(&weights->kobj); 1715 return -ENOMEM; 1716 } 1717 err = kobject_init_and_add(&goals->kobj, 1718 &damos_sysfs_quota_goals_ktype, "as->kobj, 1719 "goals"); 1720 if (err) { 1721 kobject_put(&weights->kobj); 1722 kobject_put(&goals->kobj); 1723 } else { 1724 quotas->goals = goals; 1725 } 1726 1727 return err; 1728 } 1729 1730 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas) 1731 { 1732 kobject_put("as->weights->kobj); 1733 damos_sysfs_quota_goals_rm_dirs(quotas->goals); 1734 kobject_put("as->goals->kobj); 1735 } 1736 1737 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr, 1738 char *buf) 1739 { 1740 struct damon_sysfs_quotas *quotas = container_of(kobj, 1741 struct damon_sysfs_quotas, kobj); 1742 1743 return sysfs_emit(buf, "%lu\n", quotas->ms); 1744 } 1745 1746 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr, 1747 const char *buf, size_t count) 1748 { 1749 struct damon_sysfs_quotas *quotas = container_of(kobj, 1750 struct damon_sysfs_quotas, kobj); 1751 int err = kstrtoul(buf, 0, "as->ms); 1752 1753 if (err) 1754 return -EINVAL; 1755 return count; 1756 } 1757 1758 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr, 1759 char *buf) 1760 { 1761 struct damon_sysfs_quotas *quotas = container_of(kobj, 1762 struct damon_sysfs_quotas, kobj); 1763 1764 return sysfs_emit(buf, "%lu\n", quotas->sz); 1765 } 1766 1767 static ssize_t bytes_store(struct kobject *kobj, 1768 struct kobj_attribute *attr, const char *buf, size_t count) 1769 { 1770 struct damon_sysfs_quotas *quotas = container_of(kobj, 1771 struct damon_sysfs_quotas, kobj); 1772 int err = kstrtoul(buf, 0, "as->sz); 1773 1774 if (err) 1775 return -EINVAL; 1776 return count; 1777 } 1778 1779 static ssize_t reset_interval_ms_show(struct kobject *kobj, 1780 struct kobj_attribute *attr, char *buf) 1781 { 1782 struct damon_sysfs_quotas *quotas = container_of(kobj, 1783 struct damon_sysfs_quotas, kobj); 1784 1785 return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms); 1786 } 1787 1788 static ssize_t reset_interval_ms_store(struct kobject *kobj, 1789 struct kobj_attribute *attr, const char *buf, size_t count) 1790 { 1791 struct damon_sysfs_quotas *quotas = container_of(kobj, 1792 struct damon_sysfs_quotas, kobj); 1793 int err = kstrtoul(buf, 0, "as->reset_interval_ms); 1794 1795 if (err) 1796 return -EINVAL; 1797 return count; 1798 } 1799 1800 static ssize_t effective_bytes_show(struct kobject *kobj, 1801 struct kobj_attribute *attr, char *buf) 1802 { 1803 struct damon_sysfs_quotas *quotas = container_of(kobj, 1804 struct damon_sysfs_quotas, kobj); 1805 1806 return sysfs_emit(buf, "%lu\n", quotas->effective_sz); 1807 } 1808 1809 struct damos_sysfs_qgoal_tuner_name { 1810 enum damos_quota_goal_tuner tuner; 1811 char *name; 1812 }; 1813 1814 static struct damos_sysfs_qgoal_tuner_name damos_sysfs_qgoal_tuner_names[] = { 1815 { 1816 .tuner = DAMOS_QUOTA_GOAL_TUNER_CONSIST, 1817 .name = "consist", 1818 }, 1819 { 1820 .tuner = DAMOS_QUOTA_GOAL_TUNER_TEMPORAL, 1821 .name = "temporal", 1822 }, 1823 }; 1824 1825 static ssize_t goal_tuner_show(struct kobject *kobj, 1826 struct kobj_attribute *attr, char *buf) 1827 { 1828 struct damon_sysfs_quotas *quotas = container_of(kobj, 1829 struct damon_sysfs_quotas, kobj); 1830 int i; 1831 1832 for (i = 0; i < ARRAY_SIZE(damos_sysfs_qgoal_tuner_names); i++) { 1833 struct damos_sysfs_qgoal_tuner_name *tuner_name; 1834 1835 tuner_name = &damos_sysfs_qgoal_tuner_names[i]; 1836 if (tuner_name->tuner == quotas->goal_tuner) 1837 return sysfs_emit(buf, "%s\n", tuner_name->name); 1838 } 1839 return -EINVAL; 1840 } 1841 1842 static ssize_t goal_tuner_store(struct kobject *kobj, 1843 struct kobj_attribute *attr, const char *buf, size_t count) 1844 { 1845 struct damon_sysfs_quotas *quotas = container_of(kobj, 1846 struct damon_sysfs_quotas, kobj); 1847 int i; 1848 1849 for (i = 0; i < ARRAY_SIZE(damos_sysfs_qgoal_tuner_names); i++) { 1850 struct damos_sysfs_qgoal_tuner_name *tuner_name; 1851 1852 tuner_name = &damos_sysfs_qgoal_tuner_names[i]; 1853 if (sysfs_streq(buf, tuner_name->name)) { 1854 quotas->goal_tuner = tuner_name->tuner; 1855 return count; 1856 } 1857 } 1858 return -EINVAL; 1859 } 1860 1861 static ssize_t fail_charge_num_show(struct kobject *kobj, 1862 struct kobj_attribute *attr, char *buf) 1863 { 1864 struct damon_sysfs_quotas *quotas = container_of(kobj, 1865 struct damon_sysfs_quotas, kobj); 1866 1867 return sysfs_emit(buf, "%u\n", quotas->fail_charge_num); 1868 } 1869 1870 static ssize_t fail_charge_num_store(struct kobject *kobj, 1871 struct kobj_attribute *attr, const char *buf, size_t count) 1872 { 1873 struct damon_sysfs_quotas *quotas = container_of(kobj, 1874 struct damon_sysfs_quotas, kobj); 1875 int err = kstrtouint(buf, 0, "as->fail_charge_num); 1876 1877 if (err) 1878 return -EINVAL; 1879 return count; 1880 } 1881 1882 static ssize_t fail_charge_denom_show(struct kobject *kobj, 1883 struct kobj_attribute *attr, char *buf) 1884 { 1885 struct damon_sysfs_quotas *quotas = container_of(kobj, 1886 struct damon_sysfs_quotas, kobj); 1887 1888 return sysfs_emit(buf, "%u\n", quotas->fail_charge_denom); 1889 } 1890 1891 static ssize_t fail_charge_denom_store(struct kobject *kobj, 1892 struct kobj_attribute *attr, const char *buf, size_t count) 1893 { 1894 struct damon_sysfs_quotas *quotas = container_of(kobj, 1895 struct damon_sysfs_quotas, kobj); 1896 int err = kstrtouint(buf, 0, "as->fail_charge_denom); 1897 1898 if (err) 1899 return -EINVAL; 1900 return count; 1901 } 1902 1903 static void damon_sysfs_quotas_release(struct kobject *kobj) 1904 { 1905 kfree(container_of(kobj, struct damon_sysfs_quotas, kobj)); 1906 } 1907 1908 static struct kobj_attribute damon_sysfs_quotas_ms_attr = 1909 __ATTR_RW_MODE(ms, 0600); 1910 1911 static struct kobj_attribute damon_sysfs_quotas_sz_attr = 1912 __ATTR_RW_MODE(bytes, 0600); 1913 1914 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr = 1915 __ATTR_RW_MODE(reset_interval_ms, 0600); 1916 1917 static struct kobj_attribute damon_sysfs_quotas_effective_bytes_attr = 1918 __ATTR_RO_MODE(effective_bytes, 0400); 1919 1920 static struct kobj_attribute damon_sysfs_quotas_goal_tuner_attr = 1921 __ATTR_RW_MODE(goal_tuner, 0600); 1922 1923 static struct kobj_attribute damon_sysfs_quotas_fail_charge_num_attr = 1924 __ATTR_RW_MODE(fail_charge_num, 0600); 1925 1926 static struct kobj_attribute damon_sysfs_quotas_fail_charge_denom_attr = 1927 __ATTR_RW_MODE(fail_charge_denom, 0600); 1928 1929 static struct attribute *damon_sysfs_quotas_attrs[] = { 1930 &damon_sysfs_quotas_ms_attr.attr, 1931 &damon_sysfs_quotas_sz_attr.attr, 1932 &damon_sysfs_quotas_reset_interval_ms_attr.attr, 1933 &damon_sysfs_quotas_effective_bytes_attr.attr, 1934 &damon_sysfs_quotas_goal_tuner_attr.attr, 1935 &damon_sysfs_quotas_fail_charge_num_attr.attr, 1936 &damon_sysfs_quotas_fail_charge_denom_attr.attr, 1937 NULL, 1938 }; 1939 ATTRIBUTE_GROUPS(damon_sysfs_quotas); 1940 1941 static const struct kobj_type damon_sysfs_quotas_ktype = { 1942 .release = damon_sysfs_quotas_release, 1943 .sysfs_ops = &kobj_sysfs_ops, 1944 .default_groups = damon_sysfs_quotas_groups, 1945 }; 1946 1947 /* 1948 * access_pattern directory 1949 */ 1950 1951 struct damon_sysfs_access_pattern { 1952 struct kobject kobj; 1953 struct damon_sysfs_ul_range *sz; 1954 struct damon_sysfs_ul_range *nr_accesses; 1955 struct damon_sysfs_ul_range *age; 1956 }; 1957 1958 static 1959 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void) 1960 { 1961 struct damon_sysfs_access_pattern *access_pattern = kmalloc_obj(*access_pattern); 1962 1963 if (!access_pattern) 1964 return NULL; 1965 access_pattern->kobj = (struct kobject){}; 1966 return access_pattern; 1967 } 1968 1969 static int damon_sysfs_access_pattern_add_range_dir( 1970 struct damon_sysfs_access_pattern *access_pattern, 1971 struct damon_sysfs_ul_range **range_dir_ptr, 1972 char *name) 1973 { 1974 struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0); 1975 int err; 1976 1977 if (!range) 1978 return -ENOMEM; 1979 err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype, 1980 &access_pattern->kobj, "%s", name); 1981 if (err) 1982 kobject_put(&range->kobj); 1983 else 1984 *range_dir_ptr = range; 1985 return err; 1986 } 1987 1988 static int damon_sysfs_access_pattern_add_dirs( 1989 struct damon_sysfs_access_pattern *access_pattern) 1990 { 1991 int err; 1992 1993 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1994 &access_pattern->sz, "sz"); 1995 if (err) 1996 goto put_sz_out; 1997 1998 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1999 &access_pattern->nr_accesses, "nr_accesses"); 2000 if (err) 2001 goto put_nr_accesses_sz_out; 2002 2003 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 2004 &access_pattern->age, "age"); 2005 if (err) 2006 goto put_age_nr_accesses_sz_out; 2007 return 0; 2008 2009 put_age_nr_accesses_sz_out: 2010 kobject_put(&access_pattern->age->kobj); 2011 access_pattern->age = NULL; 2012 put_nr_accesses_sz_out: 2013 kobject_put(&access_pattern->nr_accesses->kobj); 2014 access_pattern->nr_accesses = NULL; 2015 put_sz_out: 2016 kobject_put(&access_pattern->sz->kobj); 2017 access_pattern->sz = NULL; 2018 return err; 2019 } 2020 2021 static void damon_sysfs_access_pattern_rm_dirs( 2022 struct damon_sysfs_access_pattern *access_pattern) 2023 { 2024 kobject_put(&access_pattern->sz->kobj); 2025 kobject_put(&access_pattern->nr_accesses->kobj); 2026 kobject_put(&access_pattern->age->kobj); 2027 } 2028 2029 static void damon_sysfs_access_pattern_release(struct kobject *kobj) 2030 { 2031 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj)); 2032 } 2033 2034 static struct attribute *damon_sysfs_access_pattern_attrs[] = { 2035 NULL, 2036 }; 2037 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern); 2038 2039 static const struct kobj_type damon_sysfs_access_pattern_ktype = { 2040 .release = damon_sysfs_access_pattern_release, 2041 .sysfs_ops = &kobj_sysfs_ops, 2042 .default_groups = damon_sysfs_access_pattern_groups, 2043 }; 2044 2045 /* 2046 * dest (action destination) directory 2047 */ 2048 2049 struct damos_sysfs_dest { 2050 struct kobject kobj; 2051 unsigned int id; 2052 unsigned int weight; 2053 }; 2054 2055 static struct damos_sysfs_dest *damos_sysfs_dest_alloc(void) 2056 { 2057 return kzalloc_obj(struct damos_sysfs_dest); 2058 } 2059 2060 static ssize_t id_show( 2061 struct kobject *kobj, struct kobj_attribute *attr, char *buf) 2062 { 2063 struct damos_sysfs_dest *dest = container_of(kobj, 2064 struct damos_sysfs_dest, kobj); 2065 2066 return sysfs_emit(buf, "%u\n", dest->id); 2067 } 2068 2069 static ssize_t id_store(struct kobject *kobj, 2070 struct kobj_attribute *attr, const char *buf, size_t count) 2071 { 2072 struct damos_sysfs_dest *dest = container_of(kobj, 2073 struct damos_sysfs_dest, kobj); 2074 int err = kstrtouint(buf, 0, &dest->id); 2075 2076 return err ? err : count; 2077 } 2078 2079 static ssize_t weight_show( 2080 struct kobject *kobj, struct kobj_attribute *attr, char *buf) 2081 { 2082 struct damos_sysfs_dest *dest = container_of(kobj, 2083 struct damos_sysfs_dest, kobj); 2084 2085 return sysfs_emit(buf, "%u\n", dest->weight); 2086 } 2087 2088 static ssize_t weight_store(struct kobject *kobj, 2089 struct kobj_attribute *attr, const char *buf, size_t count) 2090 { 2091 struct damos_sysfs_dest *dest = container_of(kobj, 2092 struct damos_sysfs_dest, kobj); 2093 int err = kstrtouint(buf, 0, &dest->weight); 2094 2095 return err ? err : count; 2096 } 2097 2098 static void damos_sysfs_dest_release(struct kobject *kobj) 2099 { 2100 struct damos_sysfs_dest *dest = container_of(kobj, 2101 struct damos_sysfs_dest, kobj); 2102 kfree(dest); 2103 } 2104 2105 static struct kobj_attribute damos_sysfs_dest_id_attr = 2106 __ATTR_RW_MODE(id, 0600); 2107 2108 static struct kobj_attribute damos_sysfs_dest_weight_attr = 2109 __ATTR_RW_MODE(weight, 0600); 2110 2111 static struct attribute *damos_sysfs_dest_attrs[] = { 2112 &damos_sysfs_dest_id_attr.attr, 2113 &damos_sysfs_dest_weight_attr.attr, 2114 NULL, 2115 }; 2116 ATTRIBUTE_GROUPS(damos_sysfs_dest); 2117 2118 static const struct kobj_type damos_sysfs_dest_ktype = { 2119 .release = damos_sysfs_dest_release, 2120 .sysfs_ops = &kobj_sysfs_ops, 2121 .default_groups = damos_sysfs_dest_groups, 2122 }; 2123 2124 /* 2125 * dests (action destinations) directory 2126 */ 2127 2128 struct damos_sysfs_dests { 2129 struct kobject kobj; 2130 struct damos_sysfs_dest **dests_arr; 2131 int nr; 2132 }; 2133 2134 static struct damos_sysfs_dests * 2135 damos_sysfs_dests_alloc(void) 2136 { 2137 return kzalloc_obj(struct damos_sysfs_dests); 2138 } 2139 2140 static void damos_sysfs_dests_rm_dirs( 2141 struct damos_sysfs_dests *dests) 2142 { 2143 struct damos_sysfs_dest **dests_arr = dests->dests_arr; 2144 int i; 2145 2146 for (i = 0; i < dests->nr; i++) 2147 kobject_put(&dests_arr[i]->kobj); 2148 dests->nr = 0; 2149 kfree(dests_arr); 2150 dests->dests_arr = NULL; 2151 } 2152 2153 static int damos_sysfs_dests_add_dirs( 2154 struct damos_sysfs_dests *dests, int nr_dests) 2155 { 2156 struct damos_sysfs_dest **dests_arr, *dest; 2157 int err, i; 2158 2159 damos_sysfs_dests_rm_dirs(dests); 2160 if (!nr_dests) 2161 return 0; 2162 2163 dests_arr = kmalloc_objs(*dests_arr, nr_dests, 2164 GFP_KERNEL | __GFP_NOWARN); 2165 if (!dests_arr) 2166 return -ENOMEM; 2167 dests->dests_arr = dests_arr; 2168 2169 for (i = 0; i < nr_dests; i++) { 2170 dest = damos_sysfs_dest_alloc(); 2171 if (!dest) { 2172 damos_sysfs_dests_rm_dirs(dests); 2173 return -ENOMEM; 2174 } 2175 2176 err = kobject_init_and_add(&dest->kobj, 2177 &damos_sysfs_dest_ktype, 2178 &dests->kobj, "%d", i); 2179 if (err) { 2180 kobject_put(&dest->kobj); 2181 damos_sysfs_dests_rm_dirs(dests); 2182 return err; 2183 } 2184 2185 dests_arr[i] = dest; 2186 dests->nr++; 2187 } 2188 return 0; 2189 } 2190 2191 static ssize_t nr_dests_show(struct kobject *kobj, 2192 struct kobj_attribute *attr, char *buf) 2193 { 2194 struct damos_sysfs_dests *dests = container_of(kobj, 2195 struct damos_sysfs_dests, kobj); 2196 2197 return sysfs_emit(buf, "%d\n", dests->nr); 2198 } 2199 2200 static ssize_t nr_dests_store(struct kobject *kobj, 2201 struct kobj_attribute *attr, const char *buf, size_t count) 2202 { 2203 struct damos_sysfs_dests *dests; 2204 int nr, err = kstrtoint(buf, 0, &nr); 2205 2206 if (err) 2207 return err; 2208 if (nr < 0) 2209 return -EINVAL; 2210 2211 dests = container_of(kobj, struct damos_sysfs_dests, kobj); 2212 2213 if (!mutex_trylock(&damon_sysfs_lock)) 2214 return -EBUSY; 2215 err = damos_sysfs_dests_add_dirs(dests, nr); 2216 mutex_unlock(&damon_sysfs_lock); 2217 if (err) 2218 return err; 2219 2220 return count; 2221 } 2222 2223 static void damos_sysfs_dests_release(struct kobject *kobj) 2224 { 2225 kfree(container_of(kobj, struct damos_sysfs_dests, kobj)); 2226 } 2227 2228 static struct kobj_attribute damos_sysfs_dests_nr_attr = 2229 __ATTR_RW_MODE(nr_dests, 0600); 2230 2231 static struct attribute *damos_sysfs_dests_attrs[] = { 2232 &damos_sysfs_dests_nr_attr.attr, 2233 NULL, 2234 }; 2235 ATTRIBUTE_GROUPS(damos_sysfs_dests); 2236 2237 static const struct kobj_type damos_sysfs_dests_ktype = { 2238 .release = damos_sysfs_dests_release, 2239 .sysfs_ops = &kobj_sysfs_ops, 2240 .default_groups = damos_sysfs_dests_groups, 2241 }; 2242 2243 /* 2244 * scheme directory 2245 */ 2246 2247 struct damon_sysfs_scheme { 2248 struct kobject kobj; 2249 enum damos_action action; 2250 struct damon_sysfs_access_pattern *access_pattern; 2251 unsigned long apply_interval_us; 2252 struct damon_sysfs_quotas *quotas; 2253 struct damon_sysfs_watermarks *watermarks; 2254 struct damon_sysfs_scheme_filters *core_filters; 2255 struct damon_sysfs_scheme_filters *ops_filters; 2256 struct damon_sysfs_scheme_filters *filters; 2257 struct damon_sysfs_stats *stats; 2258 struct damon_sysfs_scheme_regions *tried_regions; 2259 int target_nid; 2260 struct damos_sysfs_dests *dests; 2261 }; 2262 2263 struct damos_sysfs_action_name { 2264 enum damos_action action; 2265 char *name; 2266 }; 2267 2268 static struct damos_sysfs_action_name damos_sysfs_action_names[] = { 2269 { 2270 .action = DAMOS_WILLNEED, 2271 .name = "willneed", 2272 }, 2273 { 2274 .action = DAMOS_COLD, 2275 .name = "cold", 2276 }, 2277 { 2278 .action = DAMOS_PAGEOUT, 2279 .name = "pageout", 2280 }, 2281 { 2282 .action = DAMOS_HUGEPAGE, 2283 .name = "hugepage", 2284 }, 2285 { 2286 .action = DAMOS_NOHUGEPAGE, 2287 .name = "nohugepage", 2288 }, 2289 { 2290 .action = DAMOS_COLLAPSE, 2291 .name = "collapse", 2292 }, 2293 { 2294 .action = DAMOS_LRU_PRIO, 2295 .name = "lru_prio", 2296 }, 2297 { 2298 .action = DAMOS_LRU_DEPRIO, 2299 .name = "lru_deprio", 2300 }, 2301 { 2302 .action = DAMOS_MIGRATE_HOT, 2303 .name = "migrate_hot", 2304 }, 2305 { 2306 .action = DAMOS_MIGRATE_COLD, 2307 .name = "migrate_cold", 2308 }, 2309 { 2310 .action = DAMOS_STAT, 2311 .name = "stat", 2312 }, 2313 }; 2314 2315 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc( 2316 enum damos_action action, unsigned long apply_interval_us) 2317 { 2318 struct damon_sysfs_scheme *scheme = kmalloc_obj(*scheme); 2319 2320 if (!scheme) 2321 return NULL; 2322 scheme->kobj = (struct kobject){}; 2323 scheme->action = action; 2324 scheme->apply_interval_us = apply_interval_us; 2325 scheme->target_nid = NUMA_NO_NODE; 2326 return scheme; 2327 } 2328 2329 static int damon_sysfs_scheme_set_access_pattern( 2330 struct damon_sysfs_scheme *scheme) 2331 { 2332 struct damon_sysfs_access_pattern *access_pattern; 2333 int err; 2334 2335 access_pattern = damon_sysfs_access_pattern_alloc(); 2336 if (!access_pattern) 2337 return -ENOMEM; 2338 err = kobject_init_and_add(&access_pattern->kobj, 2339 &damon_sysfs_access_pattern_ktype, &scheme->kobj, 2340 "access_pattern"); 2341 if (err) 2342 goto out; 2343 err = damon_sysfs_access_pattern_add_dirs(access_pattern); 2344 if (err) 2345 goto out; 2346 scheme->access_pattern = access_pattern; 2347 return 0; 2348 2349 out: 2350 kobject_put(&access_pattern->kobj); 2351 return err; 2352 } 2353 2354 static int damos_sysfs_set_dests(struct damon_sysfs_scheme *scheme) 2355 { 2356 struct damos_sysfs_dests *dests = damos_sysfs_dests_alloc(); 2357 int err; 2358 2359 if (!dests) 2360 return -ENOMEM; 2361 err = kobject_init_and_add(&dests->kobj, &damos_sysfs_dests_ktype, 2362 &scheme->kobj, "dests"); 2363 if (err) 2364 kobject_put(&dests->kobj); 2365 else 2366 scheme->dests = dests; 2367 return err; 2368 } 2369 2370 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme) 2371 { 2372 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc(); 2373 int err; 2374 2375 if (!quotas) 2376 return -ENOMEM; 2377 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype, 2378 &scheme->kobj, "quotas"); 2379 if (err) 2380 goto out; 2381 err = damon_sysfs_quotas_add_dirs(quotas); 2382 if (err) 2383 goto out; 2384 scheme->quotas = quotas; 2385 return 0; 2386 2387 out: 2388 kobject_put("as->kobj); 2389 return err; 2390 } 2391 2392 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme) 2393 { 2394 struct damon_sysfs_watermarks *watermarks = 2395 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0); 2396 int err; 2397 2398 if (!watermarks) 2399 return -ENOMEM; 2400 err = kobject_init_and_add(&watermarks->kobj, 2401 &damon_sysfs_watermarks_ktype, &scheme->kobj, 2402 "watermarks"); 2403 if (err) 2404 kobject_put(&watermarks->kobj); 2405 else 2406 scheme->watermarks = watermarks; 2407 return err; 2408 } 2409 2410 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme, 2411 enum damos_sysfs_filter_handle_layer layer, const char *name, 2412 struct damon_sysfs_scheme_filters **filters_ptr) 2413 { 2414 struct damon_sysfs_scheme_filters *filters = 2415 damon_sysfs_scheme_filters_alloc(layer); 2416 int err; 2417 2418 if (!filters) 2419 return -ENOMEM; 2420 err = kobject_init_and_add(&filters->kobj, 2421 &damon_sysfs_scheme_filters_ktype, &scheme->kobj, 2422 "%s", name); 2423 if (err) 2424 kobject_put(&filters->kobj); 2425 else 2426 *filters_ptr = filters; 2427 return err; 2428 } 2429 2430 static int damos_sysfs_set_filter_dirs(struct damon_sysfs_scheme *scheme) 2431 { 2432 int err; 2433 2434 err = damon_sysfs_scheme_set_filters(scheme, 2435 DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH, "filters", 2436 &scheme->filters); 2437 if (err) 2438 return err; 2439 err = damon_sysfs_scheme_set_filters(scheme, 2440 DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE, "core_filters", 2441 &scheme->core_filters); 2442 if (err) 2443 goto put_filters_out; 2444 err = damon_sysfs_scheme_set_filters(scheme, 2445 DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS, "ops_filters", 2446 &scheme->ops_filters); 2447 if (err) 2448 goto put_core_filters_out; 2449 return 0; 2450 2451 put_core_filters_out: 2452 kobject_put(&scheme->core_filters->kobj); 2453 scheme->core_filters = NULL; 2454 put_filters_out: 2455 kobject_put(&scheme->filters->kobj); 2456 scheme->filters = NULL; 2457 return err; 2458 } 2459 2460 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme) 2461 { 2462 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc(); 2463 int err; 2464 2465 if (!stats) 2466 return -ENOMEM; 2467 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype, 2468 &scheme->kobj, "stats"); 2469 if (err) 2470 kobject_put(&stats->kobj); 2471 else 2472 scheme->stats = stats; 2473 return err; 2474 } 2475 2476 static int damon_sysfs_scheme_set_tried_regions( 2477 struct damon_sysfs_scheme *scheme) 2478 { 2479 struct damon_sysfs_scheme_regions *tried_regions = 2480 damon_sysfs_scheme_regions_alloc(); 2481 int err; 2482 2483 if (!tried_regions) 2484 return -ENOMEM; 2485 err = kobject_init_and_add(&tried_regions->kobj, 2486 &damon_sysfs_scheme_regions_ktype, &scheme->kobj, 2487 "tried_regions"); 2488 if (err) 2489 kobject_put(&tried_regions->kobj); 2490 else 2491 scheme->tried_regions = tried_regions; 2492 return err; 2493 } 2494 2495 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme) 2496 { 2497 int err; 2498 2499 err = damon_sysfs_scheme_set_access_pattern(scheme); 2500 if (err) 2501 return err; 2502 err = damos_sysfs_set_dests(scheme); 2503 if (err) 2504 goto rmdir_put_access_pattern_out; 2505 err = damon_sysfs_scheme_set_quotas(scheme); 2506 if (err) 2507 goto put_dests_out; 2508 err = damon_sysfs_scheme_set_watermarks(scheme); 2509 if (err) 2510 goto rmdir_put_quotas_access_pattern_out; 2511 err = damos_sysfs_set_filter_dirs(scheme); 2512 if (err) 2513 goto put_watermarks_quotas_access_pattern_out; 2514 err = damon_sysfs_scheme_set_stats(scheme); 2515 if (err) 2516 goto put_filters_watermarks_quotas_access_pattern_out; 2517 err = damon_sysfs_scheme_set_tried_regions(scheme); 2518 if (err) 2519 goto put_tried_regions_out; 2520 return 0; 2521 2522 put_tried_regions_out: 2523 kobject_put(&scheme->tried_regions->kobj); 2524 scheme->tried_regions = NULL; 2525 put_filters_watermarks_quotas_access_pattern_out: 2526 kobject_put(&scheme->ops_filters->kobj); 2527 scheme->ops_filters = NULL; 2528 kobject_put(&scheme->core_filters->kobj); 2529 scheme->core_filters = NULL; 2530 kobject_put(&scheme->filters->kobj); 2531 scheme->filters = NULL; 2532 put_watermarks_quotas_access_pattern_out: 2533 kobject_put(&scheme->watermarks->kobj); 2534 scheme->watermarks = NULL; 2535 rmdir_put_quotas_access_pattern_out: 2536 damon_sysfs_quotas_rm_dirs(scheme->quotas); 2537 kobject_put(&scheme->quotas->kobj); 2538 scheme->quotas = NULL; 2539 put_dests_out: 2540 kobject_put(&scheme->dests->kobj); 2541 scheme->dests = NULL; 2542 rmdir_put_access_pattern_out: 2543 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 2544 kobject_put(&scheme->access_pattern->kobj); 2545 scheme->access_pattern = NULL; 2546 return err; 2547 } 2548 2549 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme) 2550 { 2551 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 2552 kobject_put(&scheme->access_pattern->kobj); 2553 damos_sysfs_dests_rm_dirs(scheme->dests); 2554 kobject_put(&scheme->dests->kobj); 2555 damon_sysfs_quotas_rm_dirs(scheme->quotas); 2556 kobject_put(&scheme->quotas->kobj); 2557 kobject_put(&scheme->watermarks->kobj); 2558 damon_sysfs_scheme_filters_rm_dirs(scheme->filters); 2559 kobject_put(&scheme->filters->kobj); 2560 damon_sysfs_scheme_filters_rm_dirs(scheme->core_filters); 2561 kobject_put(&scheme->core_filters->kobj); 2562 damon_sysfs_scheme_filters_rm_dirs(scheme->ops_filters); 2563 kobject_put(&scheme->ops_filters->kobj); 2564 kobject_put(&scheme->stats->kobj); 2565 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions); 2566 kobject_put(&scheme->tried_regions->kobj); 2567 } 2568 2569 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr, 2570 char *buf) 2571 { 2572 struct damon_sysfs_scheme *scheme = container_of(kobj, 2573 struct damon_sysfs_scheme, kobj); 2574 int i; 2575 2576 for (i = 0; i < ARRAY_SIZE(damos_sysfs_action_names); i++) { 2577 struct damos_sysfs_action_name *action_name; 2578 2579 action_name = &damos_sysfs_action_names[i]; 2580 if (action_name->action == scheme->action) 2581 return sysfs_emit(buf, "%s\n", action_name->name); 2582 } 2583 return -EINVAL; 2584 } 2585 2586 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr, 2587 const char *buf, size_t count) 2588 { 2589 struct damon_sysfs_scheme *scheme = container_of(kobj, 2590 struct damon_sysfs_scheme, kobj); 2591 int i; 2592 2593 for (i = 0; i < ARRAY_SIZE(damos_sysfs_action_names); i++) { 2594 struct damos_sysfs_action_name *action_name; 2595 2596 action_name = &damos_sysfs_action_names[i]; 2597 if (sysfs_streq(buf, action_name->name)) { 2598 scheme->action = action_name->action; 2599 return count; 2600 } 2601 } 2602 return -EINVAL; 2603 } 2604 2605 static ssize_t apply_interval_us_show(struct kobject *kobj, 2606 struct kobj_attribute *attr, char *buf) 2607 { 2608 struct damon_sysfs_scheme *scheme = container_of(kobj, 2609 struct damon_sysfs_scheme, kobj); 2610 2611 return sysfs_emit(buf, "%lu\n", scheme->apply_interval_us); 2612 } 2613 2614 static ssize_t apply_interval_us_store(struct kobject *kobj, 2615 struct kobj_attribute *attr, const char *buf, size_t count) 2616 { 2617 struct damon_sysfs_scheme *scheme = container_of(kobj, 2618 struct damon_sysfs_scheme, kobj); 2619 int err = kstrtoul(buf, 0, &scheme->apply_interval_us); 2620 2621 return err ? err : count; 2622 } 2623 2624 static ssize_t target_nid_show(struct kobject *kobj, 2625 struct kobj_attribute *attr, char *buf) 2626 { 2627 struct damon_sysfs_scheme *scheme = container_of(kobj, 2628 struct damon_sysfs_scheme, kobj); 2629 2630 return sysfs_emit(buf, "%d\n", scheme->target_nid); 2631 } 2632 2633 static ssize_t target_nid_store(struct kobject *kobj, 2634 struct kobj_attribute *attr, const char *buf, size_t count) 2635 { 2636 struct damon_sysfs_scheme *scheme = container_of(kobj, 2637 struct damon_sysfs_scheme, kobj); 2638 int err = 0; 2639 2640 err = kstrtoint(buf, 0, &scheme->target_nid); 2641 2642 return err ? err : count; 2643 } 2644 2645 static void damon_sysfs_scheme_release(struct kobject *kobj) 2646 { 2647 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj)); 2648 } 2649 2650 static struct kobj_attribute damon_sysfs_scheme_action_attr = 2651 __ATTR_RW_MODE(action, 0600); 2652 2653 static struct kobj_attribute damon_sysfs_scheme_apply_interval_us_attr = 2654 __ATTR_RW_MODE(apply_interval_us, 0600); 2655 2656 static struct kobj_attribute damon_sysfs_scheme_target_nid_attr = 2657 __ATTR_RW_MODE(target_nid, 0600); 2658 2659 static struct attribute *damon_sysfs_scheme_attrs[] = { 2660 &damon_sysfs_scheme_action_attr.attr, 2661 &damon_sysfs_scheme_apply_interval_us_attr.attr, 2662 &damon_sysfs_scheme_target_nid_attr.attr, 2663 NULL, 2664 }; 2665 ATTRIBUTE_GROUPS(damon_sysfs_scheme); 2666 2667 static const struct kobj_type damon_sysfs_scheme_ktype = { 2668 .release = damon_sysfs_scheme_release, 2669 .sysfs_ops = &kobj_sysfs_ops, 2670 .default_groups = damon_sysfs_scheme_groups, 2671 }; 2672 2673 /* 2674 * schemes directory 2675 */ 2676 2677 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void) 2678 { 2679 return kzalloc_obj(struct damon_sysfs_schemes); 2680 } 2681 2682 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes) 2683 { 2684 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr; 2685 int i; 2686 2687 for (i = 0; i < schemes->nr; i++) { 2688 damon_sysfs_scheme_rm_dirs(schemes_arr[i]); 2689 kobject_put(&schemes_arr[i]->kobj); 2690 } 2691 schemes->nr = 0; 2692 kfree(schemes_arr); 2693 schemes->schemes_arr = NULL; 2694 } 2695 2696 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes, 2697 int nr_schemes) 2698 { 2699 struct damon_sysfs_scheme **schemes_arr, *scheme; 2700 int err, i; 2701 2702 damon_sysfs_schemes_rm_dirs(schemes); 2703 if (!nr_schemes) 2704 return 0; 2705 2706 schemes_arr = kmalloc_objs(*schemes_arr, nr_schemes, 2707 GFP_KERNEL | __GFP_NOWARN); 2708 if (!schemes_arr) 2709 return -ENOMEM; 2710 schemes->schemes_arr = schemes_arr; 2711 2712 for (i = 0; i < nr_schemes; i++) { 2713 /* 2714 * apply_interval_us as 0 means same to aggregation interval 2715 * (same to before-apply_interval behavior) 2716 */ 2717 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT, 0); 2718 if (!scheme) { 2719 damon_sysfs_schemes_rm_dirs(schemes); 2720 return -ENOMEM; 2721 } 2722 2723 err = kobject_init_and_add(&scheme->kobj, 2724 &damon_sysfs_scheme_ktype, &schemes->kobj, 2725 "%d", i); 2726 if (err) 2727 goto out; 2728 err = damon_sysfs_scheme_add_dirs(scheme); 2729 if (err) 2730 goto out; 2731 2732 schemes_arr[i] = scheme; 2733 schemes->nr++; 2734 } 2735 return 0; 2736 2737 out: 2738 damon_sysfs_schemes_rm_dirs(schemes); 2739 kobject_put(&scheme->kobj); 2740 return err; 2741 } 2742 2743 static ssize_t nr_schemes_show(struct kobject *kobj, 2744 struct kobj_attribute *attr, char *buf) 2745 { 2746 struct damon_sysfs_schemes *schemes = container_of(kobj, 2747 struct damon_sysfs_schemes, kobj); 2748 2749 return sysfs_emit(buf, "%d\n", schemes->nr); 2750 } 2751 2752 static ssize_t nr_schemes_store(struct kobject *kobj, 2753 struct kobj_attribute *attr, const char *buf, size_t count) 2754 { 2755 struct damon_sysfs_schemes *schemes; 2756 int nr, err = kstrtoint(buf, 0, &nr); 2757 2758 if (err) 2759 return err; 2760 if (nr < 0) 2761 return -EINVAL; 2762 2763 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj); 2764 2765 if (!mutex_trylock(&damon_sysfs_lock)) 2766 return -EBUSY; 2767 err = damon_sysfs_schemes_add_dirs(schemes, nr); 2768 mutex_unlock(&damon_sysfs_lock); 2769 if (err) 2770 return err; 2771 return count; 2772 } 2773 2774 static void damon_sysfs_schemes_release(struct kobject *kobj) 2775 { 2776 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj)); 2777 } 2778 2779 static struct kobj_attribute damon_sysfs_schemes_nr_attr = 2780 __ATTR_RW_MODE(nr_schemes, 0600); 2781 2782 static struct attribute *damon_sysfs_schemes_attrs[] = { 2783 &damon_sysfs_schemes_nr_attr.attr, 2784 NULL, 2785 }; 2786 ATTRIBUTE_GROUPS(damon_sysfs_schemes); 2787 2788 const struct kobj_type damon_sysfs_schemes_ktype = { 2789 .release = damon_sysfs_schemes_release, 2790 .sysfs_ops = &kobj_sysfs_ops, 2791 .default_groups = damon_sysfs_schemes_groups, 2792 }; 2793 2794 static int damon_sysfs_add_scheme_filters(struct damos *scheme, 2795 struct damon_sysfs_scheme_filters *sysfs_filters) 2796 { 2797 int i; 2798 2799 for (i = 0; i < sysfs_filters->nr; i++) { 2800 struct damon_sysfs_scheme_filter *sysfs_filter = 2801 sysfs_filters->filters_arr[i]; 2802 struct damos_filter *filter = 2803 damos_new_filter(sysfs_filter->type, 2804 sysfs_filter->matching, 2805 sysfs_filter->allow); 2806 int err; 2807 2808 if (!filter) 2809 return -ENOMEM; 2810 if (filter->type == DAMOS_FILTER_TYPE_MEMCG) { 2811 err = damon_sysfs_memcg_path_to_id( 2812 sysfs_filter->memcg_path, 2813 &filter->memcg_id); 2814 if (err) { 2815 damos_destroy_filter(filter); 2816 return err; 2817 } 2818 } else if (filter->type == DAMOS_FILTER_TYPE_ADDR) { 2819 if (sysfs_filter->addr_range.end < 2820 sysfs_filter->addr_range.start) { 2821 damos_destroy_filter(filter); 2822 return -EINVAL; 2823 } 2824 filter->addr_range = sysfs_filter->addr_range; 2825 } else if (filter->type == DAMOS_FILTER_TYPE_TARGET) { 2826 filter->target_idx = sysfs_filter->target_idx; 2827 } else if (filter->type == DAMOS_FILTER_TYPE_HUGEPAGE_SIZE) { 2828 if (sysfs_filter->sz_range.min > 2829 sysfs_filter->sz_range.max) { 2830 damos_destroy_filter(filter); 2831 return -EINVAL; 2832 } 2833 filter->sz_range = sysfs_filter->sz_range; 2834 } 2835 2836 damos_add_filter(scheme, filter); 2837 } 2838 return 0; 2839 } 2840 2841 static int damos_sysfs_add_quota_score( 2842 struct damos_sysfs_quota_goals *sysfs_goals, 2843 struct damos_quota *quota) 2844 { 2845 struct damos_quota_goal *goal; 2846 int i, err; 2847 2848 for (i = 0; i < sysfs_goals->nr; i++) { 2849 struct damos_sysfs_quota_goal *sysfs_goal = 2850 sysfs_goals->goals_arr[i]; 2851 2852 if (!sysfs_goal->target_value) 2853 continue; 2854 2855 goal = damos_new_quota_goal(sysfs_goal->metric, 2856 sysfs_goal->target_value); 2857 if (!goal) 2858 return -ENOMEM; 2859 switch (sysfs_goal->metric) { 2860 case DAMOS_QUOTA_USER_INPUT: 2861 goal->current_value = sysfs_goal->current_value; 2862 break; 2863 case DAMOS_QUOTA_NODE_MEM_USED_BP: 2864 case DAMOS_QUOTA_NODE_MEM_FREE_BP: 2865 goal->nid = sysfs_goal->nid; 2866 break; 2867 case DAMOS_QUOTA_NODE_MEMCG_USED_BP: 2868 case DAMOS_QUOTA_NODE_MEMCG_FREE_BP: 2869 err = damon_sysfs_memcg_path_to_id( 2870 sysfs_goal->path, &goal->memcg_id); 2871 if (err) { 2872 damos_destroy_quota_goal(goal); 2873 return err; 2874 } 2875 goal->nid = sysfs_goal->nid; 2876 break; 2877 case DAMOS_QUOTA_NODE_ELIGIBLE_MEM_BP: 2878 goal->nid = sysfs_goal->nid; 2879 break; 2880 default: 2881 break; 2882 } 2883 damos_add_quota_goal(quota, goal); 2884 } 2885 return 0; 2886 } 2887 2888 int damos_sysfs_set_quota_scores(struct damon_sysfs_schemes *sysfs_schemes, 2889 struct damon_ctx *ctx) 2890 { 2891 struct damos *scheme; 2892 struct damos_quota quota = {}; 2893 int i = 0; 2894 2895 INIT_LIST_HEAD("a.goals); 2896 damon_for_each_scheme(scheme, ctx) { 2897 struct damon_sysfs_scheme *sysfs_scheme; 2898 struct damos_quota_goal *g, *g_next; 2899 int err; 2900 2901 /* user could have removed the scheme sysfs dir */ 2902 if (i >= sysfs_schemes->nr) 2903 break; 2904 2905 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 2906 err = damos_sysfs_add_quota_score(sysfs_scheme->quotas->goals, 2907 "a); 2908 if (err) { 2909 damos_for_each_quota_goal_safe(g, g_next, "a) 2910 damos_destroy_quota_goal(g); 2911 return err; 2912 } 2913 err = damos_commit_quota_goals(&scheme->quota, "a); 2914 damos_for_each_quota_goal_safe(g, g_next, "a) 2915 damos_destroy_quota_goal(g); 2916 if (err) 2917 return err; 2918 i++; 2919 } 2920 return 0; 2921 } 2922 2923 void damos_sysfs_update_effective_quotas( 2924 struct damon_sysfs_schemes *sysfs_schemes, 2925 struct damon_ctx *ctx) 2926 { 2927 struct damos *scheme; 2928 int schemes_idx = 0; 2929 2930 damon_for_each_scheme(scheme, ctx) { 2931 struct damon_sysfs_quotas *sysfs_quotas; 2932 2933 /* user could have removed the scheme sysfs dir */ 2934 if (schemes_idx >= sysfs_schemes->nr) 2935 break; 2936 2937 sysfs_quotas = 2938 sysfs_schemes->schemes_arr[schemes_idx++]->quotas; 2939 sysfs_quotas->effective_sz = scheme->quota.esz; 2940 } 2941 } 2942 2943 static int damos_sysfs_add_migrate_dest(struct damos *scheme, 2944 struct damos_sysfs_dests *sysfs_dests) 2945 { 2946 struct damos_migrate_dests *dests = &scheme->migrate_dests; 2947 int i; 2948 2949 dests->node_id_arr = kmalloc_objs(*dests->node_id_arr, sysfs_dests->nr); 2950 if (!dests->node_id_arr) 2951 return -ENOMEM; 2952 dests->weight_arr = kmalloc_objs(*dests->weight_arr, sysfs_dests->nr); 2953 if (!dests->weight_arr) 2954 /* ->node_id_arr will be freed by scheme destruction */ 2955 return -ENOMEM; 2956 for (i = 0; i < sysfs_dests->nr; i++) { 2957 dests->node_id_arr[i] = sysfs_dests->dests_arr[i]->id; 2958 dests->weight_arr[i] = sysfs_dests->dests_arr[i]->weight; 2959 } 2960 dests->nr_dests = sysfs_dests->nr; 2961 return 0; 2962 } 2963 2964 static struct damos *damon_sysfs_mk_scheme( 2965 struct damon_sysfs_scheme *sysfs_scheme) 2966 { 2967 struct damon_sysfs_access_pattern *access_pattern = 2968 sysfs_scheme->access_pattern; 2969 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; 2970 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; 2971 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; 2972 struct damos *scheme; 2973 int err; 2974 2975 struct damos_access_pattern pattern = { 2976 .min_sz_region = access_pattern->sz->min, 2977 .max_sz_region = access_pattern->sz->max, 2978 .min_nr_accesses = access_pattern->nr_accesses->min, 2979 .max_nr_accesses = access_pattern->nr_accesses->max, 2980 .min_age_region = access_pattern->age->min, 2981 .max_age_region = access_pattern->age->max, 2982 }; 2983 struct damos_quota quota = { 2984 .ms = sysfs_quotas->ms, 2985 .sz = sysfs_quotas->sz, 2986 .reset_interval = sysfs_quotas->reset_interval_ms, 2987 .weight_sz = sysfs_weights->sz, 2988 .weight_nr_accesses = sysfs_weights->nr_accesses, 2989 .weight_age = sysfs_weights->age, 2990 .goal_tuner = sysfs_quotas->goal_tuner, 2991 .fail_charge_num = sysfs_quotas->fail_charge_num, 2992 .fail_charge_denom = sysfs_quotas->fail_charge_denom, 2993 }; 2994 struct damos_watermarks wmarks = { 2995 .metric = sysfs_wmarks->metric, 2996 .interval = sysfs_wmarks->interval_us, 2997 .high = sysfs_wmarks->high, 2998 .mid = sysfs_wmarks->mid, 2999 .low = sysfs_wmarks->low, 3000 }; 3001 3002 scheme = damon_new_scheme(&pattern, sysfs_scheme->action, 3003 sysfs_scheme->apply_interval_us, "a, &wmarks, 3004 sysfs_scheme->target_nid); 3005 if (!scheme) 3006 return NULL; 3007 3008 err = damos_sysfs_add_quota_score(sysfs_quotas->goals, &scheme->quota); 3009 if (err) { 3010 damon_destroy_scheme(scheme); 3011 return NULL; 3012 } 3013 3014 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->core_filters); 3015 if (err) { 3016 damon_destroy_scheme(scheme); 3017 return NULL; 3018 } 3019 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->ops_filters); 3020 if (err) { 3021 damon_destroy_scheme(scheme); 3022 return NULL; 3023 } 3024 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->filters); 3025 if (err) { 3026 damon_destroy_scheme(scheme); 3027 return NULL; 3028 } 3029 err = damos_sysfs_add_migrate_dest(scheme, sysfs_scheme->dests); 3030 if (err) { 3031 damon_destroy_scheme(scheme); 3032 return NULL; 3033 } 3034 scheme->max_nr_snapshots = sysfs_scheme->stats->max_nr_snapshots; 3035 return scheme; 3036 } 3037 3038 int damon_sysfs_add_schemes(struct damon_ctx *ctx, 3039 struct damon_sysfs_schemes *sysfs_schemes) 3040 { 3041 int i; 3042 3043 for (i = 0; i < sysfs_schemes->nr; i++) { 3044 struct damos *scheme, *next; 3045 3046 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]); 3047 if (!scheme) { 3048 damon_for_each_scheme_safe(scheme, next, ctx) 3049 damon_destroy_scheme(scheme); 3050 return -ENOMEM; 3051 } 3052 damon_add_scheme(ctx, scheme); 3053 } 3054 return 0; 3055 } 3056 3057 void damon_sysfs_schemes_update_stats( 3058 struct damon_sysfs_schemes *sysfs_schemes, 3059 struct damon_ctx *ctx) 3060 { 3061 struct damos *scheme; 3062 int schemes_idx = 0; 3063 3064 damon_for_each_scheme(scheme, ctx) { 3065 struct damon_sysfs_stats *sysfs_stats; 3066 3067 /* user could have removed the scheme sysfs dir */ 3068 if (schemes_idx >= sysfs_schemes->nr) 3069 break; 3070 3071 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats; 3072 sysfs_stats->nr_tried = scheme->stat.nr_tried; 3073 sysfs_stats->sz_tried = scheme->stat.sz_tried; 3074 sysfs_stats->nr_applied = scheme->stat.nr_applied; 3075 sysfs_stats->sz_applied = scheme->stat.sz_applied; 3076 sysfs_stats->sz_ops_filter_passed = 3077 scheme->stat.sz_ops_filter_passed; 3078 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds; 3079 sysfs_stats->nr_snapshots = scheme->stat.nr_snapshots; 3080 } 3081 } 3082 3083 /** 3084 * damos_sysfs_populate_region_dir() - Populate a schemes tried region dir. 3085 * @sysfs_schemes: Schemes directory to populate regions directory. 3086 * @ctx: Corresponding DAMON context. 3087 * @t: DAMON target of @r. 3088 * @r: DAMON region to populate the directory for. 3089 * @s: Corresponding scheme. 3090 * @total_bytes_only: Whether the request is for bytes update only. 3091 * @sz_filter_passed: Bytes of @r that passed filters of @s. 3092 * 3093 * Called from DAMOS walk callback while holding damon_sysfs_lock. 3094 */ 3095 void damos_sysfs_populate_region_dir(struct damon_sysfs_schemes *sysfs_schemes, 3096 struct damon_ctx *ctx, struct damon_target *t, 3097 struct damon_region *r, struct damos *s, bool total_bytes_only, 3098 unsigned long sz_filter_passed) 3099 { 3100 struct damos *scheme; 3101 struct damon_sysfs_scheme_regions *sysfs_regions; 3102 struct damon_sysfs_scheme_region *region; 3103 int schemes_idx = 0; 3104 3105 damon_for_each_scheme(scheme, ctx) { 3106 if (scheme == s) 3107 break; 3108 schemes_idx++; 3109 } 3110 3111 /* user could have removed the scheme sysfs dir */ 3112 if (schemes_idx >= sysfs_schemes->nr) 3113 return; 3114 3115 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions; 3116 sysfs_regions->total_bytes += r->ar.end - r->ar.start; 3117 if (total_bytes_only) 3118 return; 3119 3120 region = damon_sysfs_scheme_region_alloc(r); 3121 if (!region) 3122 return; 3123 region->sz_filter_passed = sz_filter_passed; 3124 if (kobject_init_and_add(®ion->kobj, 3125 &damon_sysfs_scheme_region_ktype, 3126 &sysfs_regions->kobj, "%d", 3127 sysfs_regions->nr_regions)) 3128 goto out; 3129 if (damos_sysfs_region_add_dirs(region, ctx, r)) 3130 goto out; 3131 3132 list_add_tail(®ion->list, &sysfs_regions->regions_list); 3133 sysfs_regions->nr_regions++; 3134 return; 3135 3136 out: 3137 kobject_put(®ion->kobj); 3138 } 3139 3140 int damon_sysfs_schemes_clear_regions( 3141 struct damon_sysfs_schemes *sysfs_schemes) 3142 { 3143 int i; 3144 3145 for (i = 0; i < sysfs_schemes->nr; i++) { 3146 struct damon_sysfs_scheme *sysfs_scheme; 3147 3148 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 3149 damon_sysfs_scheme_regions_rm_dirs( 3150 sysfs_scheme->tried_regions); 3151 sysfs_scheme->tried_regions->total_bytes = 0; 3152 } 3153 return 0; 3154 } 3155