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 return err; 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_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_nr_accesses_sz_out; 2007 return 0; 2008 2009 put_nr_accesses_sz_out: 2010 kobject_put(&access_pattern->nr_accesses->kobj); 2011 access_pattern->nr_accesses = NULL; 2012 put_sz_out: 2013 kobject_put(&access_pattern->sz->kobj); 2014 access_pattern->sz = NULL; 2015 return err; 2016 } 2017 2018 static void damon_sysfs_access_pattern_rm_dirs( 2019 struct damon_sysfs_access_pattern *access_pattern) 2020 { 2021 kobject_put(&access_pattern->sz->kobj); 2022 kobject_put(&access_pattern->nr_accesses->kobj); 2023 kobject_put(&access_pattern->age->kobj); 2024 } 2025 2026 static void damon_sysfs_access_pattern_release(struct kobject *kobj) 2027 { 2028 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj)); 2029 } 2030 2031 static struct attribute *damon_sysfs_access_pattern_attrs[] = { 2032 NULL, 2033 }; 2034 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern); 2035 2036 static const struct kobj_type damon_sysfs_access_pattern_ktype = { 2037 .release = damon_sysfs_access_pattern_release, 2038 .sysfs_ops = &kobj_sysfs_ops, 2039 .default_groups = damon_sysfs_access_pattern_groups, 2040 }; 2041 2042 /* 2043 * dest (action destination) directory 2044 */ 2045 2046 struct damos_sysfs_dest { 2047 struct kobject kobj; 2048 unsigned int id; 2049 unsigned int weight; 2050 }; 2051 2052 static struct damos_sysfs_dest *damos_sysfs_dest_alloc(void) 2053 { 2054 return kzalloc_obj(struct damos_sysfs_dest); 2055 } 2056 2057 static ssize_t id_show( 2058 struct kobject *kobj, struct kobj_attribute *attr, char *buf) 2059 { 2060 struct damos_sysfs_dest *dest = container_of(kobj, 2061 struct damos_sysfs_dest, kobj); 2062 2063 return sysfs_emit(buf, "%u\n", dest->id); 2064 } 2065 2066 static ssize_t id_store(struct kobject *kobj, 2067 struct kobj_attribute *attr, const char *buf, size_t count) 2068 { 2069 struct damos_sysfs_dest *dest = container_of(kobj, 2070 struct damos_sysfs_dest, kobj); 2071 int err = kstrtouint(buf, 0, &dest->id); 2072 2073 return err ? err : count; 2074 } 2075 2076 static ssize_t weight_show( 2077 struct kobject *kobj, struct kobj_attribute *attr, char *buf) 2078 { 2079 struct damos_sysfs_dest *dest = container_of(kobj, 2080 struct damos_sysfs_dest, kobj); 2081 2082 return sysfs_emit(buf, "%u\n", dest->weight); 2083 } 2084 2085 static ssize_t weight_store(struct kobject *kobj, 2086 struct kobj_attribute *attr, const char *buf, size_t count) 2087 { 2088 struct damos_sysfs_dest *dest = container_of(kobj, 2089 struct damos_sysfs_dest, kobj); 2090 int err = kstrtouint(buf, 0, &dest->weight); 2091 2092 return err ? err : count; 2093 } 2094 2095 static void damos_sysfs_dest_release(struct kobject *kobj) 2096 { 2097 struct damos_sysfs_dest *dest = container_of(kobj, 2098 struct damos_sysfs_dest, kobj); 2099 kfree(dest); 2100 } 2101 2102 static struct kobj_attribute damos_sysfs_dest_id_attr = 2103 __ATTR_RW_MODE(id, 0600); 2104 2105 static struct kobj_attribute damos_sysfs_dest_weight_attr = 2106 __ATTR_RW_MODE(weight, 0600); 2107 2108 static struct attribute *damos_sysfs_dest_attrs[] = { 2109 &damos_sysfs_dest_id_attr.attr, 2110 &damos_sysfs_dest_weight_attr.attr, 2111 NULL, 2112 }; 2113 ATTRIBUTE_GROUPS(damos_sysfs_dest); 2114 2115 static const struct kobj_type damos_sysfs_dest_ktype = { 2116 .release = damos_sysfs_dest_release, 2117 .sysfs_ops = &kobj_sysfs_ops, 2118 .default_groups = damos_sysfs_dest_groups, 2119 }; 2120 2121 /* 2122 * dests (action destinations) directory 2123 */ 2124 2125 struct damos_sysfs_dests { 2126 struct kobject kobj; 2127 struct damos_sysfs_dest **dests_arr; 2128 int nr; 2129 }; 2130 2131 static struct damos_sysfs_dests * 2132 damos_sysfs_dests_alloc(void) 2133 { 2134 return kzalloc_obj(struct damos_sysfs_dests); 2135 } 2136 2137 static void damos_sysfs_dests_rm_dirs( 2138 struct damos_sysfs_dests *dests) 2139 { 2140 struct damos_sysfs_dest **dests_arr = dests->dests_arr; 2141 int i; 2142 2143 for (i = 0; i < dests->nr; i++) 2144 kobject_put(&dests_arr[i]->kobj); 2145 dests->nr = 0; 2146 kfree(dests_arr); 2147 dests->dests_arr = NULL; 2148 } 2149 2150 static int damos_sysfs_dests_add_dirs( 2151 struct damos_sysfs_dests *dests, int nr_dests) 2152 { 2153 struct damos_sysfs_dest **dests_arr, *dest; 2154 int err, i; 2155 2156 damos_sysfs_dests_rm_dirs(dests); 2157 if (!nr_dests) 2158 return 0; 2159 2160 dests_arr = kmalloc_objs(*dests_arr, nr_dests, 2161 GFP_KERNEL | __GFP_NOWARN); 2162 if (!dests_arr) 2163 return -ENOMEM; 2164 dests->dests_arr = dests_arr; 2165 2166 for (i = 0; i < nr_dests; i++) { 2167 dest = damos_sysfs_dest_alloc(); 2168 if (!dest) { 2169 damos_sysfs_dests_rm_dirs(dests); 2170 return -ENOMEM; 2171 } 2172 2173 err = kobject_init_and_add(&dest->kobj, 2174 &damos_sysfs_dest_ktype, 2175 &dests->kobj, "%d", i); 2176 if (err) { 2177 kobject_put(&dest->kobj); 2178 damos_sysfs_dests_rm_dirs(dests); 2179 return err; 2180 } 2181 2182 dests_arr[i] = dest; 2183 dests->nr++; 2184 } 2185 return 0; 2186 } 2187 2188 static ssize_t nr_dests_show(struct kobject *kobj, 2189 struct kobj_attribute *attr, char *buf) 2190 { 2191 struct damos_sysfs_dests *dests = container_of(kobj, 2192 struct damos_sysfs_dests, kobj); 2193 2194 return sysfs_emit(buf, "%d\n", dests->nr); 2195 } 2196 2197 static ssize_t nr_dests_store(struct kobject *kobj, 2198 struct kobj_attribute *attr, const char *buf, size_t count) 2199 { 2200 struct damos_sysfs_dests *dests; 2201 int nr, err = kstrtoint(buf, 0, &nr); 2202 2203 if (err) 2204 return err; 2205 if (nr < 0) 2206 return -EINVAL; 2207 2208 dests = container_of(kobj, struct damos_sysfs_dests, kobj); 2209 2210 if (!mutex_trylock(&damon_sysfs_lock)) 2211 return -EBUSY; 2212 err = damos_sysfs_dests_add_dirs(dests, nr); 2213 mutex_unlock(&damon_sysfs_lock); 2214 if (err) 2215 return err; 2216 2217 return count; 2218 } 2219 2220 static void damos_sysfs_dests_release(struct kobject *kobj) 2221 { 2222 kfree(container_of(kobj, struct damos_sysfs_dests, kobj)); 2223 } 2224 2225 static struct kobj_attribute damos_sysfs_dests_nr_attr = 2226 __ATTR_RW_MODE(nr_dests, 0600); 2227 2228 static struct attribute *damos_sysfs_dests_attrs[] = { 2229 &damos_sysfs_dests_nr_attr.attr, 2230 NULL, 2231 }; 2232 ATTRIBUTE_GROUPS(damos_sysfs_dests); 2233 2234 static const struct kobj_type damos_sysfs_dests_ktype = { 2235 .release = damos_sysfs_dests_release, 2236 .sysfs_ops = &kobj_sysfs_ops, 2237 .default_groups = damos_sysfs_dests_groups, 2238 }; 2239 2240 /* 2241 * scheme directory 2242 */ 2243 2244 struct damon_sysfs_scheme { 2245 struct kobject kobj; 2246 enum damos_action action; 2247 struct damon_sysfs_access_pattern *access_pattern; 2248 unsigned long apply_interval_us; 2249 struct damon_sysfs_quotas *quotas; 2250 struct damon_sysfs_watermarks *watermarks; 2251 struct damon_sysfs_scheme_filters *core_filters; 2252 struct damon_sysfs_scheme_filters *ops_filters; 2253 struct damon_sysfs_scheme_filters *filters; 2254 struct damon_sysfs_stats *stats; 2255 struct damon_sysfs_scheme_regions *tried_regions; 2256 int target_nid; 2257 struct damos_sysfs_dests *dests; 2258 }; 2259 2260 struct damos_sysfs_action_name { 2261 enum damos_action action; 2262 char *name; 2263 }; 2264 2265 static struct damos_sysfs_action_name damos_sysfs_action_names[] = { 2266 { 2267 .action = DAMOS_WILLNEED, 2268 .name = "willneed", 2269 }, 2270 { 2271 .action = DAMOS_COLD, 2272 .name = "cold", 2273 }, 2274 { 2275 .action = DAMOS_PAGEOUT, 2276 .name = "pageout", 2277 }, 2278 { 2279 .action = DAMOS_HUGEPAGE, 2280 .name = "hugepage", 2281 }, 2282 { 2283 .action = DAMOS_NOHUGEPAGE, 2284 .name = "nohugepage", 2285 }, 2286 { 2287 .action = DAMOS_COLLAPSE, 2288 .name = "collapse", 2289 }, 2290 { 2291 .action = DAMOS_LRU_PRIO, 2292 .name = "lru_prio", 2293 }, 2294 { 2295 .action = DAMOS_LRU_DEPRIO, 2296 .name = "lru_deprio", 2297 }, 2298 { 2299 .action = DAMOS_MIGRATE_HOT, 2300 .name = "migrate_hot", 2301 }, 2302 { 2303 .action = DAMOS_MIGRATE_COLD, 2304 .name = "migrate_cold", 2305 }, 2306 { 2307 .action = DAMOS_STAT, 2308 .name = "stat", 2309 }, 2310 }; 2311 2312 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc( 2313 enum damos_action action, unsigned long apply_interval_us) 2314 { 2315 struct damon_sysfs_scheme *scheme = kmalloc_obj(*scheme); 2316 2317 if (!scheme) 2318 return NULL; 2319 scheme->kobj = (struct kobject){}; 2320 scheme->action = action; 2321 scheme->apply_interval_us = apply_interval_us; 2322 scheme->target_nid = NUMA_NO_NODE; 2323 return scheme; 2324 } 2325 2326 static int damon_sysfs_scheme_set_access_pattern( 2327 struct damon_sysfs_scheme *scheme) 2328 { 2329 struct damon_sysfs_access_pattern *access_pattern; 2330 int err; 2331 2332 access_pattern = damon_sysfs_access_pattern_alloc(); 2333 if (!access_pattern) 2334 return -ENOMEM; 2335 err = kobject_init_and_add(&access_pattern->kobj, 2336 &damon_sysfs_access_pattern_ktype, &scheme->kobj, 2337 "access_pattern"); 2338 if (err) 2339 goto out; 2340 err = damon_sysfs_access_pattern_add_dirs(access_pattern); 2341 if (err) 2342 goto out; 2343 scheme->access_pattern = access_pattern; 2344 return 0; 2345 2346 out: 2347 kobject_put(&access_pattern->kobj); 2348 return err; 2349 } 2350 2351 static int damos_sysfs_set_dests(struct damon_sysfs_scheme *scheme) 2352 { 2353 struct damos_sysfs_dests *dests = damos_sysfs_dests_alloc(); 2354 int err; 2355 2356 if (!dests) 2357 return -ENOMEM; 2358 err = kobject_init_and_add(&dests->kobj, &damos_sysfs_dests_ktype, 2359 &scheme->kobj, "dests"); 2360 if (err) 2361 kobject_put(&dests->kobj); 2362 else 2363 scheme->dests = dests; 2364 return err; 2365 } 2366 2367 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme) 2368 { 2369 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc(); 2370 int err; 2371 2372 if (!quotas) 2373 return -ENOMEM; 2374 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype, 2375 &scheme->kobj, "quotas"); 2376 if (err) 2377 goto out; 2378 err = damon_sysfs_quotas_add_dirs(quotas); 2379 if (err) 2380 goto out; 2381 scheme->quotas = quotas; 2382 return 0; 2383 2384 out: 2385 kobject_put("as->kobj); 2386 return err; 2387 } 2388 2389 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme) 2390 { 2391 struct damon_sysfs_watermarks *watermarks = 2392 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0); 2393 int err; 2394 2395 if (!watermarks) 2396 return -ENOMEM; 2397 err = kobject_init_and_add(&watermarks->kobj, 2398 &damon_sysfs_watermarks_ktype, &scheme->kobj, 2399 "watermarks"); 2400 if (err) 2401 kobject_put(&watermarks->kobj); 2402 else 2403 scheme->watermarks = watermarks; 2404 return err; 2405 } 2406 2407 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme, 2408 enum damos_sysfs_filter_handle_layer layer, const char *name, 2409 struct damon_sysfs_scheme_filters **filters_ptr) 2410 { 2411 struct damon_sysfs_scheme_filters *filters = 2412 damon_sysfs_scheme_filters_alloc(layer); 2413 int err; 2414 2415 if (!filters) 2416 return -ENOMEM; 2417 err = kobject_init_and_add(&filters->kobj, 2418 &damon_sysfs_scheme_filters_ktype, &scheme->kobj, 2419 "%s", name); 2420 if (err) 2421 kobject_put(&filters->kobj); 2422 else 2423 *filters_ptr = filters; 2424 return err; 2425 } 2426 2427 static int damos_sysfs_set_filter_dirs(struct damon_sysfs_scheme *scheme) 2428 { 2429 int err; 2430 2431 err = damon_sysfs_scheme_set_filters(scheme, 2432 DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH, "filters", 2433 &scheme->filters); 2434 if (err) 2435 return err; 2436 err = damon_sysfs_scheme_set_filters(scheme, 2437 DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE, "core_filters", 2438 &scheme->core_filters); 2439 if (err) 2440 goto put_filters_out; 2441 err = damon_sysfs_scheme_set_filters(scheme, 2442 DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS, "ops_filters", 2443 &scheme->ops_filters); 2444 if (err) 2445 goto put_core_filters_out; 2446 return 0; 2447 2448 put_core_filters_out: 2449 kobject_put(&scheme->core_filters->kobj); 2450 scheme->core_filters = NULL; 2451 put_filters_out: 2452 kobject_put(&scheme->filters->kobj); 2453 scheme->filters = NULL; 2454 return err; 2455 } 2456 2457 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme) 2458 { 2459 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc(); 2460 int err; 2461 2462 if (!stats) 2463 return -ENOMEM; 2464 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype, 2465 &scheme->kobj, "stats"); 2466 if (err) 2467 kobject_put(&stats->kobj); 2468 else 2469 scheme->stats = stats; 2470 return err; 2471 } 2472 2473 static int damon_sysfs_scheme_set_tried_regions( 2474 struct damon_sysfs_scheme *scheme) 2475 { 2476 struct damon_sysfs_scheme_regions *tried_regions = 2477 damon_sysfs_scheme_regions_alloc(); 2478 int err; 2479 2480 if (!tried_regions) 2481 return -ENOMEM; 2482 err = kobject_init_and_add(&tried_regions->kobj, 2483 &damon_sysfs_scheme_regions_ktype, &scheme->kobj, 2484 "tried_regions"); 2485 if (err) 2486 kobject_put(&tried_regions->kobj); 2487 else 2488 scheme->tried_regions = tried_regions; 2489 return err; 2490 } 2491 2492 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme) 2493 { 2494 int err; 2495 2496 err = damon_sysfs_scheme_set_access_pattern(scheme); 2497 if (err) 2498 return err; 2499 err = damos_sysfs_set_dests(scheme); 2500 if (err) 2501 goto rmdir_put_access_pattern_out; 2502 err = damon_sysfs_scheme_set_quotas(scheme); 2503 if (err) 2504 goto put_dests_out; 2505 err = damon_sysfs_scheme_set_watermarks(scheme); 2506 if (err) 2507 goto rmdir_put_quotas_access_pattern_out; 2508 err = damos_sysfs_set_filter_dirs(scheme); 2509 if (err) 2510 goto put_watermarks_quotas_access_pattern_out; 2511 err = damon_sysfs_scheme_set_stats(scheme); 2512 if (err) 2513 goto put_filters_watermarks_quotas_access_pattern_out; 2514 err = damon_sysfs_scheme_set_tried_regions(scheme); 2515 if (err) 2516 goto put_stats_out; 2517 return 0; 2518 2519 put_stats_out: 2520 kobject_put(&scheme->stats->kobj); 2521 scheme->stats = NULL; 2522 put_filters_watermarks_quotas_access_pattern_out: 2523 kobject_put(&scheme->ops_filters->kobj); 2524 scheme->ops_filters = NULL; 2525 kobject_put(&scheme->core_filters->kobj); 2526 scheme->core_filters = NULL; 2527 kobject_put(&scheme->filters->kobj); 2528 scheme->filters = NULL; 2529 put_watermarks_quotas_access_pattern_out: 2530 kobject_put(&scheme->watermarks->kobj); 2531 scheme->watermarks = NULL; 2532 rmdir_put_quotas_access_pattern_out: 2533 damon_sysfs_quotas_rm_dirs(scheme->quotas); 2534 kobject_put(&scheme->quotas->kobj); 2535 scheme->quotas = NULL; 2536 put_dests_out: 2537 kobject_put(&scheme->dests->kobj); 2538 scheme->dests = NULL; 2539 rmdir_put_access_pattern_out: 2540 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 2541 kobject_put(&scheme->access_pattern->kobj); 2542 scheme->access_pattern = NULL; 2543 return err; 2544 } 2545 2546 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme) 2547 { 2548 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 2549 kobject_put(&scheme->access_pattern->kobj); 2550 damos_sysfs_dests_rm_dirs(scheme->dests); 2551 kobject_put(&scheme->dests->kobj); 2552 damon_sysfs_quotas_rm_dirs(scheme->quotas); 2553 kobject_put(&scheme->quotas->kobj); 2554 kobject_put(&scheme->watermarks->kobj); 2555 damon_sysfs_scheme_filters_rm_dirs(scheme->filters); 2556 kobject_put(&scheme->filters->kobj); 2557 damon_sysfs_scheme_filters_rm_dirs(scheme->core_filters); 2558 kobject_put(&scheme->core_filters->kobj); 2559 damon_sysfs_scheme_filters_rm_dirs(scheme->ops_filters); 2560 kobject_put(&scheme->ops_filters->kobj); 2561 kobject_put(&scheme->stats->kobj); 2562 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions); 2563 kobject_put(&scheme->tried_regions->kobj); 2564 } 2565 2566 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr, 2567 char *buf) 2568 { 2569 struct damon_sysfs_scheme *scheme = container_of(kobj, 2570 struct damon_sysfs_scheme, kobj); 2571 int i; 2572 2573 for (i = 0; i < ARRAY_SIZE(damos_sysfs_action_names); i++) { 2574 struct damos_sysfs_action_name *action_name; 2575 2576 action_name = &damos_sysfs_action_names[i]; 2577 if (action_name->action == scheme->action) 2578 return sysfs_emit(buf, "%s\n", action_name->name); 2579 } 2580 return -EINVAL; 2581 } 2582 2583 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr, 2584 const char *buf, size_t count) 2585 { 2586 struct damon_sysfs_scheme *scheme = container_of(kobj, 2587 struct damon_sysfs_scheme, kobj); 2588 int i; 2589 2590 for (i = 0; i < ARRAY_SIZE(damos_sysfs_action_names); i++) { 2591 struct damos_sysfs_action_name *action_name; 2592 2593 action_name = &damos_sysfs_action_names[i]; 2594 if (sysfs_streq(buf, action_name->name)) { 2595 scheme->action = action_name->action; 2596 return count; 2597 } 2598 } 2599 return -EINVAL; 2600 } 2601 2602 static ssize_t apply_interval_us_show(struct kobject *kobj, 2603 struct kobj_attribute *attr, char *buf) 2604 { 2605 struct damon_sysfs_scheme *scheme = container_of(kobj, 2606 struct damon_sysfs_scheme, kobj); 2607 2608 return sysfs_emit(buf, "%lu\n", scheme->apply_interval_us); 2609 } 2610 2611 static ssize_t apply_interval_us_store(struct kobject *kobj, 2612 struct kobj_attribute *attr, const char *buf, size_t count) 2613 { 2614 struct damon_sysfs_scheme *scheme = container_of(kobj, 2615 struct damon_sysfs_scheme, kobj); 2616 int err = kstrtoul(buf, 0, &scheme->apply_interval_us); 2617 2618 return err ? err : count; 2619 } 2620 2621 static ssize_t target_nid_show(struct kobject *kobj, 2622 struct kobj_attribute *attr, char *buf) 2623 { 2624 struct damon_sysfs_scheme *scheme = container_of(kobj, 2625 struct damon_sysfs_scheme, kobj); 2626 2627 return sysfs_emit(buf, "%d\n", scheme->target_nid); 2628 } 2629 2630 static ssize_t target_nid_store(struct kobject *kobj, 2631 struct kobj_attribute *attr, const char *buf, size_t count) 2632 { 2633 struct damon_sysfs_scheme *scheme = container_of(kobj, 2634 struct damon_sysfs_scheme, kobj); 2635 int err = 0; 2636 2637 err = kstrtoint(buf, 0, &scheme->target_nid); 2638 2639 return err ? err : count; 2640 } 2641 2642 static void damon_sysfs_scheme_release(struct kobject *kobj) 2643 { 2644 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj)); 2645 } 2646 2647 static struct kobj_attribute damon_sysfs_scheme_action_attr = 2648 __ATTR_RW_MODE(action, 0600); 2649 2650 static struct kobj_attribute damon_sysfs_scheme_apply_interval_us_attr = 2651 __ATTR_RW_MODE(apply_interval_us, 0600); 2652 2653 static struct kobj_attribute damon_sysfs_scheme_target_nid_attr = 2654 __ATTR_RW_MODE(target_nid, 0600); 2655 2656 static struct attribute *damon_sysfs_scheme_attrs[] = { 2657 &damon_sysfs_scheme_action_attr.attr, 2658 &damon_sysfs_scheme_apply_interval_us_attr.attr, 2659 &damon_sysfs_scheme_target_nid_attr.attr, 2660 NULL, 2661 }; 2662 ATTRIBUTE_GROUPS(damon_sysfs_scheme); 2663 2664 static const struct kobj_type damon_sysfs_scheme_ktype = { 2665 .release = damon_sysfs_scheme_release, 2666 .sysfs_ops = &kobj_sysfs_ops, 2667 .default_groups = damon_sysfs_scheme_groups, 2668 }; 2669 2670 /* 2671 * schemes directory 2672 */ 2673 2674 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void) 2675 { 2676 return kzalloc_obj(struct damon_sysfs_schemes); 2677 } 2678 2679 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes) 2680 { 2681 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr; 2682 int i; 2683 2684 for (i = 0; i < schemes->nr; i++) { 2685 damon_sysfs_scheme_rm_dirs(schemes_arr[i]); 2686 kobject_put(&schemes_arr[i]->kobj); 2687 } 2688 schemes->nr = 0; 2689 kfree(schemes_arr); 2690 schemes->schemes_arr = NULL; 2691 } 2692 2693 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes, 2694 int nr_schemes) 2695 { 2696 struct damon_sysfs_scheme **schemes_arr, *scheme; 2697 int err, i; 2698 2699 damon_sysfs_schemes_rm_dirs(schemes); 2700 if (!nr_schemes) 2701 return 0; 2702 2703 schemes_arr = kmalloc_objs(*schemes_arr, nr_schemes, 2704 GFP_KERNEL | __GFP_NOWARN); 2705 if (!schemes_arr) 2706 return -ENOMEM; 2707 schemes->schemes_arr = schemes_arr; 2708 2709 for (i = 0; i < nr_schemes; i++) { 2710 /* 2711 * apply_interval_us as 0 means same to aggregation interval 2712 * (same to before-apply_interval behavior) 2713 */ 2714 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT, 0); 2715 if (!scheme) { 2716 damon_sysfs_schemes_rm_dirs(schemes); 2717 return -ENOMEM; 2718 } 2719 2720 err = kobject_init_and_add(&scheme->kobj, 2721 &damon_sysfs_scheme_ktype, &schemes->kobj, 2722 "%d", i); 2723 if (err) 2724 goto out; 2725 err = damon_sysfs_scheme_add_dirs(scheme); 2726 if (err) 2727 goto out; 2728 2729 schemes_arr[i] = scheme; 2730 schemes->nr++; 2731 } 2732 return 0; 2733 2734 out: 2735 damon_sysfs_schemes_rm_dirs(schemes); 2736 kobject_put(&scheme->kobj); 2737 return err; 2738 } 2739 2740 static ssize_t nr_schemes_show(struct kobject *kobj, 2741 struct kobj_attribute *attr, char *buf) 2742 { 2743 struct damon_sysfs_schemes *schemes = container_of(kobj, 2744 struct damon_sysfs_schemes, kobj); 2745 2746 return sysfs_emit(buf, "%d\n", schemes->nr); 2747 } 2748 2749 static ssize_t nr_schemes_store(struct kobject *kobj, 2750 struct kobj_attribute *attr, const char *buf, size_t count) 2751 { 2752 struct damon_sysfs_schemes *schemes; 2753 int nr, err = kstrtoint(buf, 0, &nr); 2754 2755 if (err) 2756 return err; 2757 if (nr < 0) 2758 return -EINVAL; 2759 2760 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj); 2761 2762 if (!mutex_trylock(&damon_sysfs_lock)) 2763 return -EBUSY; 2764 err = damon_sysfs_schemes_add_dirs(schemes, nr); 2765 mutex_unlock(&damon_sysfs_lock); 2766 if (err) 2767 return err; 2768 return count; 2769 } 2770 2771 static void damon_sysfs_schemes_release(struct kobject *kobj) 2772 { 2773 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj)); 2774 } 2775 2776 static struct kobj_attribute damon_sysfs_schemes_nr_attr = 2777 __ATTR_RW_MODE(nr_schemes, 0600); 2778 2779 static struct attribute *damon_sysfs_schemes_attrs[] = { 2780 &damon_sysfs_schemes_nr_attr.attr, 2781 NULL, 2782 }; 2783 ATTRIBUTE_GROUPS(damon_sysfs_schemes); 2784 2785 const struct kobj_type damon_sysfs_schemes_ktype = { 2786 .release = damon_sysfs_schemes_release, 2787 .sysfs_ops = &kobj_sysfs_ops, 2788 .default_groups = damon_sysfs_schemes_groups, 2789 }; 2790 2791 static int damon_sysfs_add_scheme_filters(struct damos *scheme, 2792 struct damon_sysfs_scheme_filters *sysfs_filters) 2793 { 2794 int i; 2795 2796 for (i = 0; i < sysfs_filters->nr; i++) { 2797 struct damon_sysfs_scheme_filter *sysfs_filter = 2798 sysfs_filters->filters_arr[i]; 2799 struct damos_filter *filter = 2800 damos_new_filter(sysfs_filter->type, 2801 sysfs_filter->matching, 2802 sysfs_filter->allow); 2803 int err; 2804 2805 if (!filter) 2806 return -ENOMEM; 2807 if (filter->type == DAMOS_FILTER_TYPE_MEMCG) { 2808 err = damon_sysfs_memcg_path_to_id( 2809 sysfs_filter->memcg_path, 2810 &filter->memcg_id); 2811 if (err) { 2812 damos_destroy_filter(filter); 2813 return err; 2814 } 2815 } else if (filter->type == DAMOS_FILTER_TYPE_ADDR) { 2816 if (sysfs_filter->addr_range.end < 2817 sysfs_filter->addr_range.start) { 2818 damos_destroy_filter(filter); 2819 return -EINVAL; 2820 } 2821 filter->addr_range = sysfs_filter->addr_range; 2822 } else if (filter->type == DAMOS_FILTER_TYPE_TARGET) { 2823 filter->target_idx = sysfs_filter->target_idx; 2824 } else if (filter->type == DAMOS_FILTER_TYPE_HUGEPAGE_SIZE) { 2825 if (sysfs_filter->sz_range.min > 2826 sysfs_filter->sz_range.max) { 2827 damos_destroy_filter(filter); 2828 return -EINVAL; 2829 } 2830 filter->sz_range = sysfs_filter->sz_range; 2831 } 2832 2833 damos_add_filter(scheme, filter); 2834 } 2835 return 0; 2836 } 2837 2838 static int damos_sysfs_add_quota_score( 2839 struct damos_sysfs_quota_goals *sysfs_goals, 2840 struct damos_quota *quota) 2841 { 2842 struct damos_quota_goal *goal; 2843 int i, err; 2844 2845 for (i = 0; i < sysfs_goals->nr; i++) { 2846 struct damos_sysfs_quota_goal *sysfs_goal = 2847 sysfs_goals->goals_arr[i]; 2848 2849 if (!sysfs_goal->target_value) 2850 continue; 2851 2852 goal = damos_new_quota_goal(sysfs_goal->metric, 2853 sysfs_goal->target_value); 2854 if (!goal) 2855 return -ENOMEM; 2856 switch (sysfs_goal->metric) { 2857 case DAMOS_QUOTA_USER_INPUT: 2858 goal->current_value = sysfs_goal->current_value; 2859 break; 2860 case DAMOS_QUOTA_NODE_MEM_USED_BP: 2861 case DAMOS_QUOTA_NODE_MEM_FREE_BP: 2862 goal->nid = sysfs_goal->nid; 2863 break; 2864 case DAMOS_QUOTA_NODE_MEMCG_USED_BP: 2865 case DAMOS_QUOTA_NODE_MEMCG_FREE_BP: 2866 err = damon_sysfs_memcg_path_to_id( 2867 sysfs_goal->path, &goal->memcg_id); 2868 if (err) { 2869 damos_destroy_quota_goal(goal); 2870 return err; 2871 } 2872 goal->nid = sysfs_goal->nid; 2873 break; 2874 case DAMOS_QUOTA_NODE_ELIGIBLE_MEM_BP: 2875 goal->nid = sysfs_goal->nid; 2876 break; 2877 default: 2878 break; 2879 } 2880 damos_add_quota_goal(quota, goal); 2881 } 2882 return 0; 2883 } 2884 2885 int damos_sysfs_set_quota_scores(struct damon_sysfs_schemes *sysfs_schemes, 2886 struct damon_ctx *ctx) 2887 { 2888 struct damos *scheme; 2889 struct damos_quota quota = {}; 2890 int i = 0; 2891 2892 INIT_LIST_HEAD("a.goals); 2893 damon_for_each_scheme(scheme, ctx) { 2894 struct damon_sysfs_scheme *sysfs_scheme; 2895 struct damos_quota_goal *g, *g_next; 2896 int err; 2897 2898 /* user could have removed the scheme sysfs dir */ 2899 if (i >= sysfs_schemes->nr) 2900 break; 2901 2902 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 2903 err = damos_sysfs_add_quota_score(sysfs_scheme->quotas->goals, 2904 "a); 2905 if (err) { 2906 damos_for_each_quota_goal_safe(g, g_next, "a) 2907 damos_destroy_quota_goal(g); 2908 return err; 2909 } 2910 err = damos_commit_quota_goals(&scheme->quota, "a); 2911 damos_for_each_quota_goal_safe(g, g_next, "a) 2912 damos_destroy_quota_goal(g); 2913 if (err) 2914 return err; 2915 i++; 2916 } 2917 return 0; 2918 } 2919 2920 void damos_sysfs_update_effective_quotas( 2921 struct damon_sysfs_schemes *sysfs_schemes, 2922 struct damon_ctx *ctx) 2923 { 2924 struct damos *scheme; 2925 int schemes_idx = 0; 2926 2927 damon_for_each_scheme(scheme, ctx) { 2928 struct damon_sysfs_quotas *sysfs_quotas; 2929 2930 /* user could have removed the scheme sysfs dir */ 2931 if (schemes_idx >= sysfs_schemes->nr) 2932 break; 2933 2934 sysfs_quotas = 2935 sysfs_schemes->schemes_arr[schemes_idx++]->quotas; 2936 sysfs_quotas->effective_sz = scheme->quota.esz; 2937 } 2938 } 2939 2940 static int damos_sysfs_add_migrate_dest(struct damos *scheme, 2941 struct damos_sysfs_dests *sysfs_dests) 2942 { 2943 struct damos_migrate_dests *dests = &scheme->migrate_dests; 2944 int i; 2945 2946 dests->node_id_arr = kmalloc_objs(*dests->node_id_arr, sysfs_dests->nr); 2947 if (!dests->node_id_arr) 2948 return -ENOMEM; 2949 dests->weight_arr = kmalloc_objs(*dests->weight_arr, sysfs_dests->nr); 2950 if (!dests->weight_arr) 2951 /* ->node_id_arr will be freed by scheme destruction */ 2952 return -ENOMEM; 2953 for (i = 0; i < sysfs_dests->nr; i++) { 2954 dests->node_id_arr[i] = sysfs_dests->dests_arr[i]->id; 2955 dests->weight_arr[i] = sysfs_dests->dests_arr[i]->weight; 2956 } 2957 dests->nr_dests = sysfs_dests->nr; 2958 return 0; 2959 } 2960 2961 static struct damos *damon_sysfs_mk_scheme( 2962 struct damon_sysfs_scheme *sysfs_scheme) 2963 { 2964 struct damon_sysfs_access_pattern *access_pattern = 2965 sysfs_scheme->access_pattern; 2966 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; 2967 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; 2968 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; 2969 struct damos *scheme; 2970 int err; 2971 2972 struct damos_access_pattern pattern = { 2973 .min_sz_region = access_pattern->sz->min, 2974 .max_sz_region = access_pattern->sz->max, 2975 .min_nr_accesses = access_pattern->nr_accesses->min, 2976 .max_nr_accesses = access_pattern->nr_accesses->max, 2977 .min_age_region = access_pattern->age->min, 2978 .max_age_region = access_pattern->age->max, 2979 }; 2980 struct damos_quota quota = { 2981 .ms = sysfs_quotas->ms, 2982 .sz = sysfs_quotas->sz, 2983 .reset_interval = sysfs_quotas->reset_interval_ms, 2984 .weight_sz = sysfs_weights->sz, 2985 .weight_nr_accesses = sysfs_weights->nr_accesses, 2986 .weight_age = sysfs_weights->age, 2987 .goal_tuner = sysfs_quotas->goal_tuner, 2988 .fail_charge_num = sysfs_quotas->fail_charge_num, 2989 .fail_charge_denom = sysfs_quotas->fail_charge_denom, 2990 }; 2991 struct damos_watermarks wmarks = { 2992 .metric = sysfs_wmarks->metric, 2993 .interval = sysfs_wmarks->interval_us, 2994 .high = sysfs_wmarks->high, 2995 .mid = sysfs_wmarks->mid, 2996 .low = sysfs_wmarks->low, 2997 }; 2998 2999 scheme = damon_new_scheme(&pattern, sysfs_scheme->action, 3000 sysfs_scheme->apply_interval_us, "a, &wmarks, 3001 sysfs_scheme->target_nid); 3002 if (!scheme) 3003 return NULL; 3004 3005 err = damos_sysfs_add_quota_score(sysfs_quotas->goals, &scheme->quota); 3006 if (err) { 3007 damon_destroy_scheme(scheme); 3008 return NULL; 3009 } 3010 3011 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->core_filters); 3012 if (err) { 3013 damon_destroy_scheme(scheme); 3014 return NULL; 3015 } 3016 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->ops_filters); 3017 if (err) { 3018 damon_destroy_scheme(scheme); 3019 return NULL; 3020 } 3021 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->filters); 3022 if (err) { 3023 damon_destroy_scheme(scheme); 3024 return NULL; 3025 } 3026 err = damos_sysfs_add_migrate_dest(scheme, sysfs_scheme->dests); 3027 if (err) { 3028 damon_destroy_scheme(scheme); 3029 return NULL; 3030 } 3031 scheme->max_nr_snapshots = sysfs_scheme->stats->max_nr_snapshots; 3032 return scheme; 3033 } 3034 3035 int damon_sysfs_add_schemes(struct damon_ctx *ctx, 3036 struct damon_sysfs_schemes *sysfs_schemes) 3037 { 3038 int i; 3039 3040 for (i = 0; i < sysfs_schemes->nr; i++) { 3041 struct damos *scheme, *next; 3042 3043 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]); 3044 if (!scheme) { 3045 damon_for_each_scheme_safe(scheme, next, ctx) 3046 damon_destroy_scheme(scheme); 3047 return -ENOMEM; 3048 } 3049 damon_add_scheme(ctx, scheme); 3050 } 3051 return 0; 3052 } 3053 3054 void damon_sysfs_schemes_update_stats( 3055 struct damon_sysfs_schemes *sysfs_schemes, 3056 struct damon_ctx *ctx) 3057 { 3058 struct damos *scheme; 3059 int schemes_idx = 0; 3060 3061 damon_for_each_scheme(scheme, ctx) { 3062 struct damon_sysfs_stats *sysfs_stats; 3063 3064 /* user could have removed the scheme sysfs dir */ 3065 if (schemes_idx >= sysfs_schemes->nr) 3066 break; 3067 3068 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats; 3069 sysfs_stats->nr_tried = scheme->stat.nr_tried; 3070 sysfs_stats->sz_tried = scheme->stat.sz_tried; 3071 sysfs_stats->nr_applied = scheme->stat.nr_applied; 3072 sysfs_stats->sz_applied = scheme->stat.sz_applied; 3073 sysfs_stats->sz_ops_filter_passed = 3074 scheme->stat.sz_ops_filter_passed; 3075 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds; 3076 sysfs_stats->nr_snapshots = scheme->stat.nr_snapshots; 3077 } 3078 } 3079 3080 /** 3081 * damos_sysfs_populate_region_dir() - Populate a schemes tried region dir. 3082 * @sysfs_schemes: Schemes directory to populate regions directory. 3083 * @ctx: Corresponding DAMON context. 3084 * @t: DAMON target of @r. 3085 * @r: DAMON region to populate the directory for. 3086 * @s: Corresponding scheme. 3087 * @total_bytes_only: Whether the request is for bytes update only. 3088 * @sz_filter_passed: Bytes of @r that passed filters of @s. 3089 * 3090 * Called from DAMOS walk callback while holding damon_sysfs_lock. 3091 */ 3092 void damos_sysfs_populate_region_dir(struct damon_sysfs_schemes *sysfs_schemes, 3093 struct damon_ctx *ctx, struct damon_target *t, 3094 struct damon_region *r, struct damos *s, bool total_bytes_only, 3095 unsigned long sz_filter_passed) 3096 { 3097 struct damos *scheme; 3098 struct damon_sysfs_scheme_regions *sysfs_regions; 3099 struct damon_sysfs_scheme_region *region; 3100 int schemes_idx = 0; 3101 3102 damon_for_each_scheme(scheme, ctx) { 3103 if (scheme == s) 3104 break; 3105 schemes_idx++; 3106 } 3107 3108 /* user could have removed the scheme sysfs dir */ 3109 if (schemes_idx >= sysfs_schemes->nr) 3110 return; 3111 3112 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions; 3113 sysfs_regions->total_bytes += r->ar.end - r->ar.start; 3114 if (total_bytes_only) 3115 return; 3116 3117 region = damon_sysfs_scheme_region_alloc(r); 3118 if (!region) 3119 return; 3120 region->sz_filter_passed = sz_filter_passed; 3121 if (kobject_init_and_add(®ion->kobj, 3122 &damon_sysfs_scheme_region_ktype, 3123 &sysfs_regions->kobj, "%d", 3124 sysfs_regions->nr_regions)) 3125 goto out; 3126 if (damos_sysfs_region_add_dirs(region, ctx, r)) 3127 goto out; 3128 3129 list_add_tail(®ion->list, &sysfs_regions->regions_list); 3130 sysfs_regions->nr_regions++; 3131 return; 3132 3133 out: 3134 kobject_put(®ion->kobj); 3135 } 3136 3137 int damon_sysfs_schemes_clear_regions( 3138 struct damon_sysfs_schemes *sysfs_schemes) 3139 { 3140 int i; 3141 3142 for (i = 0; i < sysfs_schemes->nr; i++) { 3143 struct damon_sysfs_scheme *sysfs_scheme; 3144 3145 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 3146 damon_sysfs_scheme_regions_rm_dirs( 3147 sysfs_scheme->tried_regions); 3148 sysfs_scheme->tried_regions->total_bytes = 0; 3149 } 3150 return 0; 3151 } 3152