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 * scheme region directory 15 */ 16 17 struct damon_sysfs_scheme_region { 18 struct kobject kobj; 19 struct damon_addr_range ar; 20 unsigned int nr_accesses; 21 unsigned int age; 22 unsigned long sz_filter_passed; 23 struct list_head list; 24 }; 25 26 static struct damon_sysfs_scheme_region *damon_sysfs_scheme_region_alloc( 27 struct damon_region *region) 28 { 29 struct damon_sysfs_scheme_region *sysfs_region = kmalloc( 30 sizeof(*sysfs_region), GFP_KERNEL); 31 32 if (!sysfs_region) 33 return NULL; 34 sysfs_region->kobj = (struct kobject){}; 35 sysfs_region->ar = region->ar; 36 sysfs_region->nr_accesses = region->nr_accesses_bp / 10000; 37 sysfs_region->age = region->age; 38 INIT_LIST_HEAD(&sysfs_region->list); 39 return sysfs_region; 40 } 41 42 static ssize_t start_show(struct kobject *kobj, struct kobj_attribute *attr, 43 char *buf) 44 { 45 struct damon_sysfs_scheme_region *region = container_of(kobj, 46 struct damon_sysfs_scheme_region, kobj); 47 48 return sysfs_emit(buf, "%lu\n", region->ar.start); 49 } 50 51 static ssize_t end_show(struct kobject *kobj, struct kobj_attribute *attr, 52 char *buf) 53 { 54 struct damon_sysfs_scheme_region *region = container_of(kobj, 55 struct damon_sysfs_scheme_region, kobj); 56 57 return sysfs_emit(buf, "%lu\n", region->ar.end); 58 } 59 60 static ssize_t nr_accesses_show(struct kobject *kobj, 61 struct kobj_attribute *attr, char *buf) 62 { 63 struct damon_sysfs_scheme_region *region = container_of(kobj, 64 struct damon_sysfs_scheme_region, kobj); 65 66 return sysfs_emit(buf, "%u\n", region->nr_accesses); 67 } 68 69 static ssize_t age_show(struct kobject *kobj, struct kobj_attribute *attr, 70 char *buf) 71 { 72 struct damon_sysfs_scheme_region *region = container_of(kobj, 73 struct damon_sysfs_scheme_region, kobj); 74 75 return sysfs_emit(buf, "%u\n", region->age); 76 } 77 78 static ssize_t sz_filter_passed_show(struct kobject *kobj, 79 struct kobj_attribute *attr, char *buf) 80 { 81 struct damon_sysfs_scheme_region *region = container_of(kobj, 82 struct damon_sysfs_scheme_region, kobj); 83 84 return sysfs_emit(buf, "%lu\n", region->sz_filter_passed); 85 } 86 87 static void damon_sysfs_scheme_region_release(struct kobject *kobj) 88 { 89 struct damon_sysfs_scheme_region *region = container_of(kobj, 90 struct damon_sysfs_scheme_region, kobj); 91 92 list_del(®ion->list); 93 kfree(region); 94 } 95 96 static struct kobj_attribute damon_sysfs_scheme_region_start_attr = 97 __ATTR_RO_MODE(start, 0400); 98 99 static struct kobj_attribute damon_sysfs_scheme_region_end_attr = 100 __ATTR_RO_MODE(end, 0400); 101 102 static struct kobj_attribute damon_sysfs_scheme_region_nr_accesses_attr = 103 __ATTR_RO_MODE(nr_accesses, 0400); 104 105 static struct kobj_attribute damon_sysfs_scheme_region_age_attr = 106 __ATTR_RO_MODE(age, 0400); 107 108 static struct kobj_attribute damon_sysfs_scheme_region_sz_filter_passed_attr = 109 __ATTR_RO_MODE(sz_filter_passed, 0400); 110 111 static struct attribute *damon_sysfs_scheme_region_attrs[] = { 112 &damon_sysfs_scheme_region_start_attr.attr, 113 &damon_sysfs_scheme_region_end_attr.attr, 114 &damon_sysfs_scheme_region_nr_accesses_attr.attr, 115 &damon_sysfs_scheme_region_age_attr.attr, 116 &damon_sysfs_scheme_region_sz_filter_passed_attr.attr, 117 NULL, 118 }; 119 ATTRIBUTE_GROUPS(damon_sysfs_scheme_region); 120 121 static const struct kobj_type damon_sysfs_scheme_region_ktype = { 122 .release = damon_sysfs_scheme_region_release, 123 .sysfs_ops = &kobj_sysfs_ops, 124 .default_groups = damon_sysfs_scheme_region_groups, 125 }; 126 127 /* 128 * scheme regions directory 129 */ 130 131 struct damon_sysfs_scheme_regions { 132 struct kobject kobj; 133 struct list_head regions_list; 134 int nr_regions; 135 unsigned long total_bytes; 136 }; 137 138 static struct damon_sysfs_scheme_regions * 139 damon_sysfs_scheme_regions_alloc(void) 140 { 141 struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions), 142 GFP_KERNEL); 143 144 if (!regions) 145 return NULL; 146 147 regions->kobj = (struct kobject){}; 148 INIT_LIST_HEAD(®ions->regions_list); 149 regions->nr_regions = 0; 150 regions->total_bytes = 0; 151 return regions; 152 } 153 154 static ssize_t total_bytes_show(struct kobject *kobj, 155 struct kobj_attribute *attr, char *buf) 156 { 157 struct damon_sysfs_scheme_regions *regions = container_of(kobj, 158 struct damon_sysfs_scheme_regions, kobj); 159 160 return sysfs_emit(buf, "%lu\n", regions->total_bytes); 161 } 162 163 static void damon_sysfs_scheme_regions_rm_dirs( 164 struct damon_sysfs_scheme_regions *regions) 165 { 166 struct damon_sysfs_scheme_region *r, *next; 167 168 list_for_each_entry_safe(r, next, ®ions->regions_list, list) { 169 /* release function deletes it from the list */ 170 kobject_put(&r->kobj); 171 regions->nr_regions--; 172 } 173 } 174 175 static void damon_sysfs_scheme_regions_release(struct kobject *kobj) 176 { 177 kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj)); 178 } 179 180 static struct kobj_attribute damon_sysfs_scheme_regions_total_bytes_attr = 181 __ATTR_RO_MODE(total_bytes, 0400); 182 183 static struct attribute *damon_sysfs_scheme_regions_attrs[] = { 184 &damon_sysfs_scheme_regions_total_bytes_attr.attr, 185 NULL, 186 }; 187 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions); 188 189 static const struct kobj_type damon_sysfs_scheme_regions_ktype = { 190 .release = damon_sysfs_scheme_regions_release, 191 .sysfs_ops = &kobj_sysfs_ops, 192 .default_groups = damon_sysfs_scheme_regions_groups, 193 }; 194 195 /* 196 * schemes/stats directory 197 */ 198 199 struct damon_sysfs_stats { 200 struct kobject kobj; 201 unsigned long nr_tried; 202 unsigned long sz_tried; 203 unsigned long nr_applied; 204 unsigned long sz_applied; 205 unsigned long sz_ops_filter_passed; 206 unsigned long qt_exceeds; 207 }; 208 209 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void) 210 { 211 return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL); 212 } 213 214 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr, 215 char *buf) 216 { 217 struct damon_sysfs_stats *stats = container_of(kobj, 218 struct damon_sysfs_stats, kobj); 219 220 return sysfs_emit(buf, "%lu\n", stats->nr_tried); 221 } 222 223 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr, 224 char *buf) 225 { 226 struct damon_sysfs_stats *stats = container_of(kobj, 227 struct damon_sysfs_stats, kobj); 228 229 return sysfs_emit(buf, "%lu\n", stats->sz_tried); 230 } 231 232 static ssize_t nr_applied_show(struct kobject *kobj, 233 struct kobj_attribute *attr, char *buf) 234 { 235 struct damon_sysfs_stats *stats = container_of(kobj, 236 struct damon_sysfs_stats, kobj); 237 238 return sysfs_emit(buf, "%lu\n", stats->nr_applied); 239 } 240 241 static ssize_t sz_applied_show(struct kobject *kobj, 242 struct kobj_attribute *attr, char *buf) 243 { 244 struct damon_sysfs_stats *stats = container_of(kobj, 245 struct damon_sysfs_stats, kobj); 246 247 return sysfs_emit(buf, "%lu\n", stats->sz_applied); 248 } 249 250 static ssize_t sz_ops_filter_passed_show(struct kobject *kobj, 251 struct kobj_attribute *attr, char *buf) 252 { 253 struct damon_sysfs_stats *stats = container_of(kobj, 254 struct damon_sysfs_stats, kobj); 255 256 return sysfs_emit(buf, "%lu\n", stats->sz_ops_filter_passed); 257 } 258 259 static ssize_t qt_exceeds_show(struct kobject *kobj, 260 struct kobj_attribute *attr, char *buf) 261 { 262 struct damon_sysfs_stats *stats = container_of(kobj, 263 struct damon_sysfs_stats, kobj); 264 265 return sysfs_emit(buf, "%lu\n", stats->qt_exceeds); 266 } 267 268 static void damon_sysfs_stats_release(struct kobject *kobj) 269 { 270 kfree(container_of(kobj, struct damon_sysfs_stats, kobj)); 271 } 272 273 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr = 274 __ATTR_RO_MODE(nr_tried, 0400); 275 276 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr = 277 __ATTR_RO_MODE(sz_tried, 0400); 278 279 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr = 280 __ATTR_RO_MODE(nr_applied, 0400); 281 282 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr = 283 __ATTR_RO_MODE(sz_applied, 0400); 284 285 static struct kobj_attribute damon_sysfs_stats_sz_ops_filter_passed_attr = 286 __ATTR_RO_MODE(sz_ops_filter_passed, 0400); 287 288 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr = 289 __ATTR_RO_MODE(qt_exceeds, 0400); 290 291 static struct attribute *damon_sysfs_stats_attrs[] = { 292 &damon_sysfs_stats_nr_tried_attr.attr, 293 &damon_sysfs_stats_sz_tried_attr.attr, 294 &damon_sysfs_stats_nr_applied_attr.attr, 295 &damon_sysfs_stats_sz_applied_attr.attr, 296 &damon_sysfs_stats_sz_ops_filter_passed_attr.attr, 297 &damon_sysfs_stats_qt_exceeds_attr.attr, 298 NULL, 299 }; 300 ATTRIBUTE_GROUPS(damon_sysfs_stats); 301 302 static const struct kobj_type damon_sysfs_stats_ktype = { 303 .release = damon_sysfs_stats_release, 304 .sysfs_ops = &kobj_sysfs_ops, 305 .default_groups = damon_sysfs_stats_groups, 306 }; 307 308 /* 309 * filter directory 310 */ 311 312 /* 313 * enum damos_sysfs_filter_handle_layer - Layers handling filters of a dir. 314 */ 315 enum damos_sysfs_filter_handle_layer { 316 DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE, 317 DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS, 318 DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH, 319 }; 320 321 struct damon_sysfs_scheme_filter { 322 struct kobject kobj; 323 enum damos_sysfs_filter_handle_layer handle_layer; 324 enum damos_filter_type type; 325 bool matching; 326 bool allow; 327 char *memcg_path; 328 struct damon_addr_range addr_range; 329 struct damon_size_range sz_range; 330 int target_idx; 331 }; 332 333 static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc( 334 enum damos_sysfs_filter_handle_layer layer) 335 { 336 struct damon_sysfs_scheme_filter *filter; 337 338 filter = kzalloc(sizeof(struct damon_sysfs_scheme_filter), GFP_KERNEL); 339 if (filter) 340 filter->handle_layer = layer; 341 return filter; 342 } 343 344 /* Should match with enum damos_filter_type */ 345 static const char * const damon_sysfs_scheme_filter_type_strs[] = { 346 "anon", 347 "active", 348 "memcg", 349 "young", 350 "hugepage_size", 351 "unmapped", 352 "addr", 353 "target", 354 }; 355 356 static ssize_t type_show(struct kobject *kobj, 357 struct kobj_attribute *attr, char *buf) 358 { 359 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 360 struct damon_sysfs_scheme_filter, kobj); 361 362 return sysfs_emit(buf, "%s\n", 363 damon_sysfs_scheme_filter_type_strs[filter->type]); 364 } 365 366 static bool damos_sysfs_scheme_filter_valid_type( 367 enum damos_sysfs_filter_handle_layer layer, 368 enum damos_filter_type type) 369 { 370 switch (layer) { 371 case DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH: 372 return true; 373 case DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE: 374 return !damos_filter_for_ops(type); 375 case DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS: 376 return damos_filter_for_ops(type); 377 default: 378 break; 379 } 380 return false; 381 } 382 383 static ssize_t type_store(struct kobject *kobj, 384 struct kobj_attribute *attr, const char *buf, size_t count) 385 { 386 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 387 struct damon_sysfs_scheme_filter, kobj); 388 enum damos_filter_type type; 389 ssize_t ret = -EINVAL; 390 391 for (type = 0; type < NR_DAMOS_FILTER_TYPES; type++) { 392 if (sysfs_streq(buf, damon_sysfs_scheme_filter_type_strs[ 393 type])) { 394 if (!damos_sysfs_scheme_filter_valid_type( 395 filter->handle_layer, type)) 396 break; 397 filter->type = type; 398 ret = count; 399 break; 400 } 401 } 402 return ret; 403 } 404 405 static ssize_t matching_show(struct kobject *kobj, 406 struct kobj_attribute *attr, char *buf) 407 { 408 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 409 struct damon_sysfs_scheme_filter, kobj); 410 411 return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N'); 412 } 413 414 static ssize_t matching_store(struct kobject *kobj, 415 struct kobj_attribute *attr, const char *buf, size_t count) 416 { 417 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 418 struct damon_sysfs_scheme_filter, kobj); 419 bool matching; 420 int err = kstrtobool(buf, &matching); 421 422 if (err) 423 return err; 424 425 filter->matching = matching; 426 return count; 427 } 428 429 static ssize_t allow_show(struct kobject *kobj, 430 struct kobj_attribute *attr, char *buf) 431 { 432 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 433 struct damon_sysfs_scheme_filter, kobj); 434 435 return sysfs_emit(buf, "%c\n", filter->allow ? 'Y' : 'N'); 436 } 437 438 static ssize_t allow_store(struct kobject *kobj, 439 struct kobj_attribute *attr, const char *buf, size_t count) 440 { 441 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 442 struct damon_sysfs_scheme_filter, kobj); 443 bool allow; 444 int err = kstrtobool(buf, &allow); 445 446 if (err) 447 return err; 448 449 filter->allow = allow; 450 return count; 451 } 452 453 static ssize_t memcg_path_show(struct kobject *kobj, 454 struct kobj_attribute *attr, char *buf) 455 { 456 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 457 struct damon_sysfs_scheme_filter, kobj); 458 459 return sysfs_emit(buf, "%s\n", 460 filter->memcg_path ? filter->memcg_path : ""); 461 } 462 463 static ssize_t memcg_path_store(struct kobject *kobj, 464 struct kobj_attribute *attr, const char *buf, size_t count) 465 { 466 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 467 struct damon_sysfs_scheme_filter, kobj); 468 char *path = kmalloc(sizeof(*path) * (count + 1), GFP_KERNEL); 469 470 if (!path) 471 return -ENOMEM; 472 473 strscpy(path, buf, count + 1); 474 filter->memcg_path = path; 475 return count; 476 } 477 478 static ssize_t addr_start_show(struct kobject *kobj, 479 struct kobj_attribute *attr, char *buf) 480 { 481 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 482 struct damon_sysfs_scheme_filter, kobj); 483 484 return sysfs_emit(buf, "%lu\n", filter->addr_range.start); 485 } 486 487 static ssize_t addr_start_store(struct kobject *kobj, 488 struct kobj_attribute *attr, const char *buf, size_t count) 489 { 490 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 491 struct damon_sysfs_scheme_filter, kobj); 492 int err = kstrtoul(buf, 0, &filter->addr_range.start); 493 494 return err ? err : count; 495 } 496 497 static ssize_t addr_end_show(struct kobject *kobj, 498 struct kobj_attribute *attr, char *buf) 499 { 500 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 501 struct damon_sysfs_scheme_filter, kobj); 502 503 return sysfs_emit(buf, "%lu\n", filter->addr_range.end); 504 } 505 506 static ssize_t addr_end_store(struct kobject *kobj, 507 struct kobj_attribute *attr, const char *buf, size_t count) 508 { 509 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 510 struct damon_sysfs_scheme_filter, kobj); 511 int err = kstrtoul(buf, 0, &filter->addr_range.end); 512 513 return err ? err : count; 514 } 515 516 static ssize_t min_show(struct kobject *kobj, 517 struct kobj_attribute *attr, char *buf) 518 { 519 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 520 struct damon_sysfs_scheme_filter, kobj); 521 522 return sysfs_emit(buf, "%lu\n", filter->sz_range.min); 523 } 524 525 static ssize_t min_store(struct kobject *kobj, 526 struct kobj_attribute *attr, const char *buf, size_t count) 527 { 528 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 529 struct damon_sysfs_scheme_filter, kobj); 530 int err = kstrtoul(buf, 0, &filter->sz_range.min); 531 532 return err ? err : count; 533 } 534 535 static ssize_t max_show(struct kobject *kobj, 536 struct kobj_attribute *attr, char *buf) 537 { 538 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 539 struct damon_sysfs_scheme_filter, kobj); 540 541 return sysfs_emit(buf, "%lu\n", filter->sz_range.max); 542 } 543 544 static ssize_t max_store(struct kobject *kobj, 545 struct kobj_attribute *attr, const char *buf, size_t count) 546 { 547 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 548 struct damon_sysfs_scheme_filter, kobj); 549 int err = kstrtoul(buf, 0, &filter->sz_range.max); 550 551 return err ? err : count; 552 } 553 554 static ssize_t damon_target_idx_show(struct kobject *kobj, 555 struct kobj_attribute *attr, char *buf) 556 { 557 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 558 struct damon_sysfs_scheme_filter, kobj); 559 560 return sysfs_emit(buf, "%d\n", filter->target_idx); 561 } 562 563 static ssize_t damon_target_idx_store(struct kobject *kobj, 564 struct kobj_attribute *attr, const char *buf, size_t count) 565 { 566 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 567 struct damon_sysfs_scheme_filter, kobj); 568 int err = kstrtoint(buf, 0, &filter->target_idx); 569 570 return err ? err : count; 571 } 572 573 static void damon_sysfs_scheme_filter_release(struct kobject *kobj) 574 { 575 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 576 struct damon_sysfs_scheme_filter, kobj); 577 578 kfree(filter->memcg_path); 579 kfree(filter); 580 } 581 582 static struct kobj_attribute damon_sysfs_scheme_filter_type_attr = 583 __ATTR_RW_MODE(type, 0600); 584 585 static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr = 586 __ATTR_RW_MODE(matching, 0600); 587 588 static struct kobj_attribute damon_sysfs_scheme_filter_allow_attr = 589 __ATTR_RW_MODE(allow, 0600); 590 591 static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr = 592 __ATTR_RW_MODE(memcg_path, 0600); 593 594 static struct kobj_attribute damon_sysfs_scheme_filter_addr_start_attr = 595 __ATTR_RW_MODE(addr_start, 0600); 596 597 static struct kobj_attribute damon_sysfs_scheme_filter_addr_end_attr = 598 __ATTR_RW_MODE(addr_end, 0600); 599 600 static struct kobj_attribute damon_sysfs_scheme_filter_min_attr = 601 __ATTR_RW_MODE(min, 0600); 602 603 static struct kobj_attribute damon_sysfs_scheme_filter_max_attr = 604 __ATTR_RW_MODE(max, 0600); 605 606 static struct kobj_attribute damon_sysfs_scheme_filter_damon_target_idx_attr = 607 __ATTR_RW_MODE(damon_target_idx, 0600); 608 609 static struct attribute *damon_sysfs_scheme_filter_attrs[] = { 610 &damon_sysfs_scheme_filter_type_attr.attr, 611 &damon_sysfs_scheme_filter_matching_attr.attr, 612 &damon_sysfs_scheme_filter_allow_attr.attr, 613 &damon_sysfs_scheme_filter_memcg_path_attr.attr, 614 &damon_sysfs_scheme_filter_addr_start_attr.attr, 615 &damon_sysfs_scheme_filter_addr_end_attr.attr, 616 &damon_sysfs_scheme_filter_min_attr.attr, 617 &damon_sysfs_scheme_filter_max_attr.attr, 618 &damon_sysfs_scheme_filter_damon_target_idx_attr.attr, 619 NULL, 620 }; 621 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter); 622 623 static const struct kobj_type damon_sysfs_scheme_filter_ktype = { 624 .release = damon_sysfs_scheme_filter_release, 625 .sysfs_ops = &kobj_sysfs_ops, 626 .default_groups = damon_sysfs_scheme_filter_groups, 627 }; 628 629 /* 630 * filters directory 631 */ 632 633 struct damon_sysfs_scheme_filters { 634 struct kobject kobj; 635 enum damos_sysfs_filter_handle_layer handle_layer; 636 struct damon_sysfs_scheme_filter **filters_arr; 637 int nr; 638 }; 639 640 static struct damon_sysfs_scheme_filters * 641 damon_sysfs_scheme_filters_alloc(enum damos_sysfs_filter_handle_layer layer) 642 { 643 struct damon_sysfs_scheme_filters *filters; 644 645 filters = kzalloc(sizeof(struct damon_sysfs_scheme_filters), GFP_KERNEL); 646 if (filters) 647 filters->handle_layer = layer; 648 return filters; 649 } 650 651 static void damon_sysfs_scheme_filters_rm_dirs( 652 struct damon_sysfs_scheme_filters *filters) 653 { 654 struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr; 655 int i; 656 657 for (i = 0; i < filters->nr; i++) 658 kobject_put(&filters_arr[i]->kobj); 659 filters->nr = 0; 660 kfree(filters_arr); 661 filters->filters_arr = NULL; 662 } 663 664 static int damon_sysfs_scheme_filters_add_dirs( 665 struct damon_sysfs_scheme_filters *filters, int nr_filters) 666 { 667 struct damon_sysfs_scheme_filter **filters_arr, *filter; 668 int err, i; 669 670 damon_sysfs_scheme_filters_rm_dirs(filters); 671 if (!nr_filters) 672 return 0; 673 674 filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr), 675 GFP_KERNEL | __GFP_NOWARN); 676 if (!filters_arr) 677 return -ENOMEM; 678 filters->filters_arr = filters_arr; 679 680 for (i = 0; i < nr_filters; i++) { 681 filter = damon_sysfs_scheme_filter_alloc( 682 filters->handle_layer); 683 if (!filter) { 684 damon_sysfs_scheme_filters_rm_dirs(filters); 685 return -ENOMEM; 686 } 687 688 err = kobject_init_and_add(&filter->kobj, 689 &damon_sysfs_scheme_filter_ktype, 690 &filters->kobj, "%d", i); 691 if (err) { 692 kobject_put(&filter->kobj); 693 damon_sysfs_scheme_filters_rm_dirs(filters); 694 return err; 695 } 696 697 filters_arr[i] = filter; 698 filters->nr++; 699 } 700 return 0; 701 } 702 703 static ssize_t nr_filters_show(struct kobject *kobj, 704 struct kobj_attribute *attr, char *buf) 705 { 706 struct damon_sysfs_scheme_filters *filters = container_of(kobj, 707 struct damon_sysfs_scheme_filters, kobj); 708 709 return sysfs_emit(buf, "%d\n", filters->nr); 710 } 711 712 static ssize_t nr_filters_store(struct kobject *kobj, 713 struct kobj_attribute *attr, const char *buf, size_t count) 714 { 715 struct damon_sysfs_scheme_filters *filters; 716 int nr, err = kstrtoint(buf, 0, &nr); 717 718 if (err) 719 return err; 720 if (nr < 0) 721 return -EINVAL; 722 723 filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj); 724 725 if (!mutex_trylock(&damon_sysfs_lock)) 726 return -EBUSY; 727 err = damon_sysfs_scheme_filters_add_dirs(filters, nr); 728 mutex_unlock(&damon_sysfs_lock); 729 if (err) 730 return err; 731 732 return count; 733 } 734 735 static void damon_sysfs_scheme_filters_release(struct kobject *kobj) 736 { 737 kfree(container_of(kobj, struct damon_sysfs_scheme_filters, kobj)); 738 } 739 740 static struct kobj_attribute damon_sysfs_scheme_filters_nr_attr = 741 __ATTR_RW_MODE(nr_filters, 0600); 742 743 static struct attribute *damon_sysfs_scheme_filters_attrs[] = { 744 &damon_sysfs_scheme_filters_nr_attr.attr, 745 NULL, 746 }; 747 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filters); 748 749 static const struct kobj_type damon_sysfs_scheme_filters_ktype = { 750 .release = damon_sysfs_scheme_filters_release, 751 .sysfs_ops = &kobj_sysfs_ops, 752 .default_groups = damon_sysfs_scheme_filters_groups, 753 }; 754 755 /* 756 * watermarks directory 757 */ 758 759 struct damon_sysfs_watermarks { 760 struct kobject kobj; 761 enum damos_wmark_metric metric; 762 unsigned long interval_us; 763 unsigned long high; 764 unsigned long mid; 765 unsigned long low; 766 }; 767 768 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc( 769 enum damos_wmark_metric metric, unsigned long interval_us, 770 unsigned long high, unsigned long mid, unsigned long low) 771 { 772 struct damon_sysfs_watermarks *watermarks = kmalloc( 773 sizeof(*watermarks), GFP_KERNEL); 774 775 if (!watermarks) 776 return NULL; 777 watermarks->kobj = (struct kobject){}; 778 watermarks->metric = metric; 779 watermarks->interval_us = interval_us; 780 watermarks->high = high; 781 watermarks->mid = mid; 782 watermarks->low = low; 783 return watermarks; 784 } 785 786 /* Should match with enum damos_wmark_metric */ 787 static const char * const damon_sysfs_wmark_metric_strs[] = { 788 "none", 789 "free_mem_rate", 790 }; 791 792 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr, 793 char *buf) 794 { 795 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 796 struct damon_sysfs_watermarks, kobj); 797 798 return sysfs_emit(buf, "%s\n", 799 damon_sysfs_wmark_metric_strs[watermarks->metric]); 800 } 801 802 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr, 803 const char *buf, size_t count) 804 { 805 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 806 struct damon_sysfs_watermarks, kobj); 807 enum damos_wmark_metric metric; 808 809 for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) { 810 if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) { 811 watermarks->metric = metric; 812 return count; 813 } 814 } 815 return -EINVAL; 816 } 817 818 static ssize_t interval_us_show(struct kobject *kobj, 819 struct kobj_attribute *attr, char *buf) 820 { 821 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 822 struct damon_sysfs_watermarks, kobj); 823 824 return sysfs_emit(buf, "%lu\n", watermarks->interval_us); 825 } 826 827 static ssize_t interval_us_store(struct kobject *kobj, 828 struct kobj_attribute *attr, const char *buf, size_t count) 829 { 830 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 831 struct damon_sysfs_watermarks, kobj); 832 int err = kstrtoul(buf, 0, &watermarks->interval_us); 833 834 return err ? err : count; 835 } 836 837 static ssize_t high_show(struct kobject *kobj, 838 struct kobj_attribute *attr, char *buf) 839 { 840 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 841 struct damon_sysfs_watermarks, kobj); 842 843 return sysfs_emit(buf, "%lu\n", watermarks->high); 844 } 845 846 static ssize_t high_store(struct kobject *kobj, 847 struct kobj_attribute *attr, const char *buf, size_t count) 848 { 849 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 850 struct damon_sysfs_watermarks, kobj); 851 int err = kstrtoul(buf, 0, &watermarks->high); 852 853 return err ? err : count; 854 } 855 856 static ssize_t mid_show(struct kobject *kobj, 857 struct kobj_attribute *attr, char *buf) 858 { 859 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 860 struct damon_sysfs_watermarks, kobj); 861 862 return sysfs_emit(buf, "%lu\n", watermarks->mid); 863 } 864 865 static ssize_t mid_store(struct kobject *kobj, 866 struct kobj_attribute *attr, const char *buf, size_t count) 867 { 868 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 869 struct damon_sysfs_watermarks, kobj); 870 int err = kstrtoul(buf, 0, &watermarks->mid); 871 872 return err ? err : count; 873 } 874 875 static ssize_t low_show(struct kobject *kobj, 876 struct kobj_attribute *attr, char *buf) 877 { 878 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 879 struct damon_sysfs_watermarks, kobj); 880 881 return sysfs_emit(buf, "%lu\n", watermarks->low); 882 } 883 884 static ssize_t low_store(struct kobject *kobj, 885 struct kobj_attribute *attr, const char *buf, size_t count) 886 { 887 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 888 struct damon_sysfs_watermarks, kobj); 889 int err = kstrtoul(buf, 0, &watermarks->low); 890 891 return err ? err : count; 892 } 893 894 static void damon_sysfs_watermarks_release(struct kobject *kobj) 895 { 896 kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj)); 897 } 898 899 static struct kobj_attribute damon_sysfs_watermarks_metric_attr = 900 __ATTR_RW_MODE(metric, 0600); 901 902 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr = 903 __ATTR_RW_MODE(interval_us, 0600); 904 905 static struct kobj_attribute damon_sysfs_watermarks_high_attr = 906 __ATTR_RW_MODE(high, 0600); 907 908 static struct kobj_attribute damon_sysfs_watermarks_mid_attr = 909 __ATTR_RW_MODE(mid, 0600); 910 911 static struct kobj_attribute damon_sysfs_watermarks_low_attr = 912 __ATTR_RW_MODE(low, 0600); 913 914 static struct attribute *damon_sysfs_watermarks_attrs[] = { 915 &damon_sysfs_watermarks_metric_attr.attr, 916 &damon_sysfs_watermarks_interval_us_attr.attr, 917 &damon_sysfs_watermarks_high_attr.attr, 918 &damon_sysfs_watermarks_mid_attr.attr, 919 &damon_sysfs_watermarks_low_attr.attr, 920 NULL, 921 }; 922 ATTRIBUTE_GROUPS(damon_sysfs_watermarks); 923 924 static const struct kobj_type damon_sysfs_watermarks_ktype = { 925 .release = damon_sysfs_watermarks_release, 926 .sysfs_ops = &kobj_sysfs_ops, 927 .default_groups = damon_sysfs_watermarks_groups, 928 }; 929 930 /* 931 * quota goal directory 932 */ 933 934 struct damos_sysfs_quota_goal { 935 struct kobject kobj; 936 enum damos_quota_goal_metric metric; 937 unsigned long target_value; 938 unsigned long current_value; 939 }; 940 941 /* This should match with enum damos_action */ 942 static const char * const damos_sysfs_quota_goal_metric_strs[] = { 943 "user_input", 944 "some_mem_psi_us", 945 }; 946 947 static struct damos_sysfs_quota_goal *damos_sysfs_quota_goal_alloc(void) 948 { 949 return kzalloc(sizeof(struct damos_sysfs_quota_goal), GFP_KERNEL); 950 } 951 952 static ssize_t target_metric_show(struct kobject *kobj, 953 struct kobj_attribute *attr, char *buf) 954 { 955 struct damos_sysfs_quota_goal *goal = container_of(kobj, 956 struct damos_sysfs_quota_goal, kobj); 957 958 return sysfs_emit(buf, "%s\n", 959 damos_sysfs_quota_goal_metric_strs[goal->metric]); 960 } 961 962 static ssize_t target_metric_store(struct kobject *kobj, 963 struct kobj_attribute *attr, const char *buf, size_t count) 964 { 965 struct damos_sysfs_quota_goal *goal = container_of(kobj, 966 struct damos_sysfs_quota_goal, kobj); 967 enum damos_quota_goal_metric m; 968 969 for (m = 0; m < NR_DAMOS_QUOTA_GOAL_METRICS; m++) { 970 if (sysfs_streq(buf, damos_sysfs_quota_goal_metric_strs[m])) { 971 goal->metric = m; 972 return count; 973 } 974 } 975 return -EINVAL; 976 } 977 978 static ssize_t target_value_show(struct kobject *kobj, 979 struct kobj_attribute *attr, char *buf) 980 { 981 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 982 damos_sysfs_quota_goal, kobj); 983 984 return sysfs_emit(buf, "%lu\n", goal->target_value); 985 } 986 987 static ssize_t target_value_store(struct kobject *kobj, 988 struct kobj_attribute *attr, const char *buf, size_t count) 989 { 990 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 991 damos_sysfs_quota_goal, kobj); 992 int err = kstrtoul(buf, 0, &goal->target_value); 993 994 return err ? err : count; 995 } 996 997 static ssize_t current_value_show(struct kobject *kobj, 998 struct kobj_attribute *attr, char *buf) 999 { 1000 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1001 damos_sysfs_quota_goal, kobj); 1002 1003 return sysfs_emit(buf, "%lu\n", goal->current_value); 1004 } 1005 1006 static ssize_t current_value_store(struct kobject *kobj, 1007 struct kobj_attribute *attr, const char *buf, size_t count) 1008 { 1009 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1010 damos_sysfs_quota_goal, kobj); 1011 int err = kstrtoul(buf, 0, &goal->current_value); 1012 1013 /* feed callback should check existence of this file and read value */ 1014 return err ? err : count; 1015 } 1016 1017 static void damos_sysfs_quota_goal_release(struct kobject *kobj) 1018 { 1019 /* or, notify this release to the feed callback */ 1020 kfree(container_of(kobj, struct damos_sysfs_quota_goal, kobj)); 1021 } 1022 1023 static struct kobj_attribute damos_sysfs_quota_goal_target_metric_attr = 1024 __ATTR_RW_MODE(target_metric, 0600); 1025 1026 static struct kobj_attribute damos_sysfs_quota_goal_target_value_attr = 1027 __ATTR_RW_MODE(target_value, 0600); 1028 1029 static struct kobj_attribute damos_sysfs_quota_goal_current_value_attr = 1030 __ATTR_RW_MODE(current_value, 0600); 1031 1032 static struct attribute *damos_sysfs_quota_goal_attrs[] = { 1033 &damos_sysfs_quota_goal_target_metric_attr.attr, 1034 &damos_sysfs_quota_goal_target_value_attr.attr, 1035 &damos_sysfs_quota_goal_current_value_attr.attr, 1036 NULL, 1037 }; 1038 ATTRIBUTE_GROUPS(damos_sysfs_quota_goal); 1039 1040 static const struct kobj_type damos_sysfs_quota_goal_ktype = { 1041 .release = damos_sysfs_quota_goal_release, 1042 .sysfs_ops = &kobj_sysfs_ops, 1043 .default_groups = damos_sysfs_quota_goal_groups, 1044 }; 1045 1046 /* 1047 * quota goals directory 1048 */ 1049 1050 struct damos_sysfs_quota_goals { 1051 struct kobject kobj; 1052 struct damos_sysfs_quota_goal **goals_arr; /* counted by nr */ 1053 int nr; 1054 }; 1055 1056 static struct damos_sysfs_quota_goals *damos_sysfs_quota_goals_alloc(void) 1057 { 1058 return kzalloc(sizeof(struct damos_sysfs_quota_goals), GFP_KERNEL); 1059 } 1060 1061 static void damos_sysfs_quota_goals_rm_dirs( 1062 struct damos_sysfs_quota_goals *goals) 1063 { 1064 struct damos_sysfs_quota_goal **goals_arr = goals->goals_arr; 1065 int i; 1066 1067 for (i = 0; i < goals->nr; i++) 1068 kobject_put(&goals_arr[i]->kobj); 1069 goals->nr = 0; 1070 kfree(goals_arr); 1071 goals->goals_arr = NULL; 1072 } 1073 1074 static int damos_sysfs_quota_goals_add_dirs( 1075 struct damos_sysfs_quota_goals *goals, int nr_goals) 1076 { 1077 struct damos_sysfs_quota_goal **goals_arr, *goal; 1078 int err, i; 1079 1080 damos_sysfs_quota_goals_rm_dirs(goals); 1081 if (!nr_goals) 1082 return 0; 1083 1084 goals_arr = kmalloc_array(nr_goals, sizeof(*goals_arr), 1085 GFP_KERNEL | __GFP_NOWARN); 1086 if (!goals_arr) 1087 return -ENOMEM; 1088 goals->goals_arr = goals_arr; 1089 1090 for (i = 0; i < nr_goals; i++) { 1091 goal = damos_sysfs_quota_goal_alloc(); 1092 if (!goal) { 1093 damos_sysfs_quota_goals_rm_dirs(goals); 1094 return -ENOMEM; 1095 } 1096 1097 err = kobject_init_and_add(&goal->kobj, 1098 &damos_sysfs_quota_goal_ktype, &goals->kobj, 1099 "%d", i); 1100 if (err) { 1101 kobject_put(&goal->kobj); 1102 damos_sysfs_quota_goals_rm_dirs(goals); 1103 return err; 1104 } 1105 1106 goals_arr[i] = goal; 1107 goals->nr++; 1108 } 1109 return 0; 1110 } 1111 1112 static ssize_t nr_goals_show(struct kobject *kobj, 1113 struct kobj_attribute *attr, char *buf) 1114 { 1115 struct damos_sysfs_quota_goals *goals = container_of(kobj, 1116 struct damos_sysfs_quota_goals, kobj); 1117 1118 return sysfs_emit(buf, "%d\n", goals->nr); 1119 } 1120 1121 static ssize_t nr_goals_store(struct kobject *kobj, 1122 struct kobj_attribute *attr, const char *buf, size_t count) 1123 { 1124 struct damos_sysfs_quota_goals *goals; 1125 int nr, err = kstrtoint(buf, 0, &nr); 1126 1127 if (err) 1128 return err; 1129 if (nr < 0) 1130 return -EINVAL; 1131 1132 goals = container_of(kobj, struct damos_sysfs_quota_goals, kobj); 1133 1134 if (!mutex_trylock(&damon_sysfs_lock)) 1135 return -EBUSY; 1136 err = damos_sysfs_quota_goals_add_dirs(goals, nr); 1137 mutex_unlock(&damon_sysfs_lock); 1138 if (err) 1139 return err; 1140 1141 return count; 1142 } 1143 1144 static void damos_sysfs_quota_goals_release(struct kobject *kobj) 1145 { 1146 kfree(container_of(kobj, struct damos_sysfs_quota_goals, kobj)); 1147 } 1148 1149 static struct kobj_attribute damos_sysfs_quota_goals_nr_attr = 1150 __ATTR_RW_MODE(nr_goals, 0600); 1151 1152 static struct attribute *damos_sysfs_quota_goals_attrs[] = { 1153 &damos_sysfs_quota_goals_nr_attr.attr, 1154 NULL, 1155 }; 1156 ATTRIBUTE_GROUPS(damos_sysfs_quota_goals); 1157 1158 static const struct kobj_type damos_sysfs_quota_goals_ktype = { 1159 .release = damos_sysfs_quota_goals_release, 1160 .sysfs_ops = &kobj_sysfs_ops, 1161 .default_groups = damos_sysfs_quota_goals_groups, 1162 }; 1163 1164 /* 1165 * scheme/weights directory 1166 */ 1167 1168 struct damon_sysfs_weights { 1169 struct kobject kobj; 1170 unsigned int sz; 1171 unsigned int nr_accesses; 1172 unsigned int age; 1173 }; 1174 1175 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz, 1176 unsigned int nr_accesses, unsigned int age) 1177 { 1178 struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights), 1179 GFP_KERNEL); 1180 1181 if (!weights) 1182 return NULL; 1183 weights->kobj = (struct kobject){}; 1184 weights->sz = sz; 1185 weights->nr_accesses = nr_accesses; 1186 weights->age = age; 1187 return weights; 1188 } 1189 1190 static ssize_t sz_permil_show(struct kobject *kobj, 1191 struct kobj_attribute *attr, char *buf) 1192 { 1193 struct damon_sysfs_weights *weights = container_of(kobj, 1194 struct damon_sysfs_weights, kobj); 1195 1196 return sysfs_emit(buf, "%u\n", weights->sz); 1197 } 1198 1199 static ssize_t sz_permil_store(struct kobject *kobj, 1200 struct kobj_attribute *attr, const char *buf, size_t count) 1201 { 1202 struct damon_sysfs_weights *weights = container_of(kobj, 1203 struct damon_sysfs_weights, kobj); 1204 int err = kstrtouint(buf, 0, &weights->sz); 1205 1206 return err ? err : count; 1207 } 1208 1209 static ssize_t nr_accesses_permil_show(struct kobject *kobj, 1210 struct kobj_attribute *attr, char *buf) 1211 { 1212 struct damon_sysfs_weights *weights = container_of(kobj, 1213 struct damon_sysfs_weights, kobj); 1214 1215 return sysfs_emit(buf, "%u\n", weights->nr_accesses); 1216 } 1217 1218 static ssize_t nr_accesses_permil_store(struct kobject *kobj, 1219 struct kobj_attribute *attr, const char *buf, size_t count) 1220 { 1221 struct damon_sysfs_weights *weights = container_of(kobj, 1222 struct damon_sysfs_weights, kobj); 1223 int err = kstrtouint(buf, 0, &weights->nr_accesses); 1224 1225 return err ? err : count; 1226 } 1227 1228 static ssize_t age_permil_show(struct kobject *kobj, 1229 struct kobj_attribute *attr, char *buf) 1230 { 1231 struct damon_sysfs_weights *weights = container_of(kobj, 1232 struct damon_sysfs_weights, kobj); 1233 1234 return sysfs_emit(buf, "%u\n", weights->age); 1235 } 1236 1237 static ssize_t age_permil_store(struct kobject *kobj, 1238 struct kobj_attribute *attr, const char *buf, size_t count) 1239 { 1240 struct damon_sysfs_weights *weights = container_of(kobj, 1241 struct damon_sysfs_weights, kobj); 1242 int err = kstrtouint(buf, 0, &weights->age); 1243 1244 return err ? err : count; 1245 } 1246 1247 static void damon_sysfs_weights_release(struct kobject *kobj) 1248 { 1249 kfree(container_of(kobj, struct damon_sysfs_weights, kobj)); 1250 } 1251 1252 static struct kobj_attribute damon_sysfs_weights_sz_attr = 1253 __ATTR_RW_MODE(sz_permil, 0600); 1254 1255 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr = 1256 __ATTR_RW_MODE(nr_accesses_permil, 0600); 1257 1258 static struct kobj_attribute damon_sysfs_weights_age_attr = 1259 __ATTR_RW_MODE(age_permil, 0600); 1260 1261 static struct attribute *damon_sysfs_weights_attrs[] = { 1262 &damon_sysfs_weights_sz_attr.attr, 1263 &damon_sysfs_weights_nr_accesses_attr.attr, 1264 &damon_sysfs_weights_age_attr.attr, 1265 NULL, 1266 }; 1267 ATTRIBUTE_GROUPS(damon_sysfs_weights); 1268 1269 static const struct kobj_type damon_sysfs_weights_ktype = { 1270 .release = damon_sysfs_weights_release, 1271 .sysfs_ops = &kobj_sysfs_ops, 1272 .default_groups = damon_sysfs_weights_groups, 1273 }; 1274 1275 /* 1276 * quotas directory 1277 */ 1278 1279 struct damon_sysfs_quotas { 1280 struct kobject kobj; 1281 struct damon_sysfs_weights *weights; 1282 struct damos_sysfs_quota_goals *goals; 1283 unsigned long ms; 1284 unsigned long sz; 1285 unsigned long reset_interval_ms; 1286 unsigned long effective_sz; /* Effective size quota in bytes */ 1287 }; 1288 1289 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void) 1290 { 1291 return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL); 1292 } 1293 1294 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas) 1295 { 1296 struct damon_sysfs_weights *weights; 1297 struct damos_sysfs_quota_goals *goals; 1298 int err; 1299 1300 weights = damon_sysfs_weights_alloc(0, 0, 0); 1301 if (!weights) 1302 return -ENOMEM; 1303 1304 err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype, 1305 "as->kobj, "weights"); 1306 if (err) { 1307 kobject_put(&weights->kobj); 1308 return err; 1309 } 1310 quotas->weights = weights; 1311 1312 goals = damos_sysfs_quota_goals_alloc(); 1313 if (!goals) { 1314 kobject_put(&weights->kobj); 1315 return -ENOMEM; 1316 } 1317 err = kobject_init_and_add(&goals->kobj, 1318 &damos_sysfs_quota_goals_ktype, "as->kobj, 1319 "goals"); 1320 if (err) { 1321 kobject_put(&weights->kobj); 1322 kobject_put(&goals->kobj); 1323 } else { 1324 quotas->goals = goals; 1325 } 1326 1327 return err; 1328 } 1329 1330 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas) 1331 { 1332 kobject_put("as->weights->kobj); 1333 damos_sysfs_quota_goals_rm_dirs(quotas->goals); 1334 kobject_put("as->goals->kobj); 1335 } 1336 1337 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr, 1338 char *buf) 1339 { 1340 struct damon_sysfs_quotas *quotas = container_of(kobj, 1341 struct damon_sysfs_quotas, kobj); 1342 1343 return sysfs_emit(buf, "%lu\n", quotas->ms); 1344 } 1345 1346 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr, 1347 const char *buf, size_t count) 1348 { 1349 struct damon_sysfs_quotas *quotas = container_of(kobj, 1350 struct damon_sysfs_quotas, kobj); 1351 int err = kstrtoul(buf, 0, "as->ms); 1352 1353 if (err) 1354 return -EINVAL; 1355 return count; 1356 } 1357 1358 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr, 1359 char *buf) 1360 { 1361 struct damon_sysfs_quotas *quotas = container_of(kobj, 1362 struct damon_sysfs_quotas, kobj); 1363 1364 return sysfs_emit(buf, "%lu\n", quotas->sz); 1365 } 1366 1367 static ssize_t bytes_store(struct kobject *kobj, 1368 struct kobj_attribute *attr, const char *buf, size_t count) 1369 { 1370 struct damon_sysfs_quotas *quotas = container_of(kobj, 1371 struct damon_sysfs_quotas, kobj); 1372 int err = kstrtoul(buf, 0, "as->sz); 1373 1374 if (err) 1375 return -EINVAL; 1376 return count; 1377 } 1378 1379 static ssize_t reset_interval_ms_show(struct kobject *kobj, 1380 struct kobj_attribute *attr, char *buf) 1381 { 1382 struct damon_sysfs_quotas *quotas = container_of(kobj, 1383 struct damon_sysfs_quotas, kobj); 1384 1385 return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms); 1386 } 1387 1388 static ssize_t reset_interval_ms_store(struct kobject *kobj, 1389 struct kobj_attribute *attr, const char *buf, size_t count) 1390 { 1391 struct damon_sysfs_quotas *quotas = container_of(kobj, 1392 struct damon_sysfs_quotas, kobj); 1393 int err = kstrtoul(buf, 0, "as->reset_interval_ms); 1394 1395 if (err) 1396 return -EINVAL; 1397 return count; 1398 } 1399 1400 static ssize_t effective_bytes_show(struct kobject *kobj, 1401 struct kobj_attribute *attr, char *buf) 1402 { 1403 struct damon_sysfs_quotas *quotas = container_of(kobj, 1404 struct damon_sysfs_quotas, kobj); 1405 1406 return sysfs_emit(buf, "%lu\n", quotas->effective_sz); 1407 } 1408 1409 static void damon_sysfs_quotas_release(struct kobject *kobj) 1410 { 1411 kfree(container_of(kobj, struct damon_sysfs_quotas, kobj)); 1412 } 1413 1414 static struct kobj_attribute damon_sysfs_quotas_ms_attr = 1415 __ATTR_RW_MODE(ms, 0600); 1416 1417 static struct kobj_attribute damon_sysfs_quotas_sz_attr = 1418 __ATTR_RW_MODE(bytes, 0600); 1419 1420 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr = 1421 __ATTR_RW_MODE(reset_interval_ms, 0600); 1422 1423 static struct kobj_attribute damon_sysfs_quotas_effective_bytes_attr = 1424 __ATTR_RO_MODE(effective_bytes, 0400); 1425 1426 static struct attribute *damon_sysfs_quotas_attrs[] = { 1427 &damon_sysfs_quotas_ms_attr.attr, 1428 &damon_sysfs_quotas_sz_attr.attr, 1429 &damon_sysfs_quotas_reset_interval_ms_attr.attr, 1430 &damon_sysfs_quotas_effective_bytes_attr.attr, 1431 NULL, 1432 }; 1433 ATTRIBUTE_GROUPS(damon_sysfs_quotas); 1434 1435 static const struct kobj_type damon_sysfs_quotas_ktype = { 1436 .release = damon_sysfs_quotas_release, 1437 .sysfs_ops = &kobj_sysfs_ops, 1438 .default_groups = damon_sysfs_quotas_groups, 1439 }; 1440 1441 /* 1442 * access_pattern directory 1443 */ 1444 1445 struct damon_sysfs_access_pattern { 1446 struct kobject kobj; 1447 struct damon_sysfs_ul_range *sz; 1448 struct damon_sysfs_ul_range *nr_accesses; 1449 struct damon_sysfs_ul_range *age; 1450 }; 1451 1452 static 1453 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void) 1454 { 1455 struct damon_sysfs_access_pattern *access_pattern = 1456 kmalloc(sizeof(*access_pattern), GFP_KERNEL); 1457 1458 if (!access_pattern) 1459 return NULL; 1460 access_pattern->kobj = (struct kobject){}; 1461 return access_pattern; 1462 } 1463 1464 static int damon_sysfs_access_pattern_add_range_dir( 1465 struct damon_sysfs_access_pattern *access_pattern, 1466 struct damon_sysfs_ul_range **range_dir_ptr, 1467 char *name) 1468 { 1469 struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0); 1470 int err; 1471 1472 if (!range) 1473 return -ENOMEM; 1474 err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype, 1475 &access_pattern->kobj, "%s", name); 1476 if (err) 1477 kobject_put(&range->kobj); 1478 else 1479 *range_dir_ptr = range; 1480 return err; 1481 } 1482 1483 static int damon_sysfs_access_pattern_add_dirs( 1484 struct damon_sysfs_access_pattern *access_pattern) 1485 { 1486 int err; 1487 1488 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1489 &access_pattern->sz, "sz"); 1490 if (err) 1491 goto put_sz_out; 1492 1493 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1494 &access_pattern->nr_accesses, "nr_accesses"); 1495 if (err) 1496 goto put_nr_accesses_sz_out; 1497 1498 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1499 &access_pattern->age, "age"); 1500 if (err) 1501 goto put_age_nr_accesses_sz_out; 1502 return 0; 1503 1504 put_age_nr_accesses_sz_out: 1505 kobject_put(&access_pattern->age->kobj); 1506 access_pattern->age = NULL; 1507 put_nr_accesses_sz_out: 1508 kobject_put(&access_pattern->nr_accesses->kobj); 1509 access_pattern->nr_accesses = NULL; 1510 put_sz_out: 1511 kobject_put(&access_pattern->sz->kobj); 1512 access_pattern->sz = NULL; 1513 return err; 1514 } 1515 1516 static void damon_sysfs_access_pattern_rm_dirs( 1517 struct damon_sysfs_access_pattern *access_pattern) 1518 { 1519 kobject_put(&access_pattern->sz->kobj); 1520 kobject_put(&access_pattern->nr_accesses->kobj); 1521 kobject_put(&access_pattern->age->kobj); 1522 } 1523 1524 static void damon_sysfs_access_pattern_release(struct kobject *kobj) 1525 { 1526 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj)); 1527 } 1528 1529 static struct attribute *damon_sysfs_access_pattern_attrs[] = { 1530 NULL, 1531 }; 1532 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern); 1533 1534 static const struct kobj_type damon_sysfs_access_pattern_ktype = { 1535 .release = damon_sysfs_access_pattern_release, 1536 .sysfs_ops = &kobj_sysfs_ops, 1537 .default_groups = damon_sysfs_access_pattern_groups, 1538 }; 1539 1540 /* 1541 * scheme directory 1542 */ 1543 1544 struct damon_sysfs_scheme { 1545 struct kobject kobj; 1546 enum damos_action action; 1547 struct damon_sysfs_access_pattern *access_pattern; 1548 unsigned long apply_interval_us; 1549 struct damon_sysfs_quotas *quotas; 1550 struct damon_sysfs_watermarks *watermarks; 1551 struct damon_sysfs_scheme_filters *core_filters; 1552 struct damon_sysfs_scheme_filters *ops_filters; 1553 struct damon_sysfs_scheme_filters *filters; 1554 struct damon_sysfs_stats *stats; 1555 struct damon_sysfs_scheme_regions *tried_regions; 1556 int target_nid; 1557 }; 1558 1559 /* This should match with enum damos_action */ 1560 static const char * const damon_sysfs_damos_action_strs[] = { 1561 "willneed", 1562 "cold", 1563 "pageout", 1564 "hugepage", 1565 "nohugepage", 1566 "lru_prio", 1567 "lru_deprio", 1568 "migrate_hot", 1569 "migrate_cold", 1570 "stat", 1571 }; 1572 1573 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc( 1574 enum damos_action action, unsigned long apply_interval_us) 1575 { 1576 struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme), 1577 GFP_KERNEL); 1578 1579 if (!scheme) 1580 return NULL; 1581 scheme->kobj = (struct kobject){}; 1582 scheme->action = action; 1583 scheme->apply_interval_us = apply_interval_us; 1584 scheme->target_nid = NUMA_NO_NODE; 1585 return scheme; 1586 } 1587 1588 static int damon_sysfs_scheme_set_access_pattern( 1589 struct damon_sysfs_scheme *scheme) 1590 { 1591 struct damon_sysfs_access_pattern *access_pattern; 1592 int err; 1593 1594 access_pattern = damon_sysfs_access_pattern_alloc(); 1595 if (!access_pattern) 1596 return -ENOMEM; 1597 err = kobject_init_and_add(&access_pattern->kobj, 1598 &damon_sysfs_access_pattern_ktype, &scheme->kobj, 1599 "access_pattern"); 1600 if (err) 1601 goto out; 1602 err = damon_sysfs_access_pattern_add_dirs(access_pattern); 1603 if (err) 1604 goto out; 1605 scheme->access_pattern = access_pattern; 1606 return 0; 1607 1608 out: 1609 kobject_put(&access_pattern->kobj); 1610 return err; 1611 } 1612 1613 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme) 1614 { 1615 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc(); 1616 int err; 1617 1618 if (!quotas) 1619 return -ENOMEM; 1620 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype, 1621 &scheme->kobj, "quotas"); 1622 if (err) 1623 goto out; 1624 err = damon_sysfs_quotas_add_dirs(quotas); 1625 if (err) 1626 goto out; 1627 scheme->quotas = quotas; 1628 return 0; 1629 1630 out: 1631 kobject_put("as->kobj); 1632 return err; 1633 } 1634 1635 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme) 1636 { 1637 struct damon_sysfs_watermarks *watermarks = 1638 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0); 1639 int err; 1640 1641 if (!watermarks) 1642 return -ENOMEM; 1643 err = kobject_init_and_add(&watermarks->kobj, 1644 &damon_sysfs_watermarks_ktype, &scheme->kobj, 1645 "watermarks"); 1646 if (err) 1647 kobject_put(&watermarks->kobj); 1648 else 1649 scheme->watermarks = watermarks; 1650 return err; 1651 } 1652 1653 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme, 1654 enum damos_sysfs_filter_handle_layer layer, const char *name, 1655 struct damon_sysfs_scheme_filters **filters_ptr) 1656 { 1657 struct damon_sysfs_scheme_filters *filters = 1658 damon_sysfs_scheme_filters_alloc(layer); 1659 int err; 1660 1661 if (!filters) 1662 return -ENOMEM; 1663 err = kobject_init_and_add(&filters->kobj, 1664 &damon_sysfs_scheme_filters_ktype, &scheme->kobj, 1665 "%s", name); 1666 if (err) 1667 kobject_put(&filters->kobj); 1668 else 1669 *filters_ptr = filters; 1670 return err; 1671 } 1672 1673 static int damos_sysfs_set_filter_dirs(struct damon_sysfs_scheme *scheme) 1674 { 1675 int err; 1676 1677 err = damon_sysfs_scheme_set_filters(scheme, 1678 DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH, "filters", 1679 &scheme->filters); 1680 if (err) 1681 return err; 1682 err = damon_sysfs_scheme_set_filters(scheme, 1683 DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE, "core_filters", 1684 &scheme->core_filters); 1685 if (err) 1686 goto put_filters_out; 1687 err = damon_sysfs_scheme_set_filters(scheme, 1688 DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS, "ops_filters", 1689 &scheme->ops_filters); 1690 if (err) 1691 goto put_core_filters_out; 1692 return 0; 1693 1694 put_core_filters_out: 1695 kobject_put(&scheme->core_filters->kobj); 1696 scheme->core_filters = NULL; 1697 put_filters_out: 1698 kobject_put(&scheme->filters->kobj); 1699 scheme->filters = NULL; 1700 return err; 1701 } 1702 1703 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme) 1704 { 1705 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc(); 1706 int err; 1707 1708 if (!stats) 1709 return -ENOMEM; 1710 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype, 1711 &scheme->kobj, "stats"); 1712 if (err) 1713 kobject_put(&stats->kobj); 1714 else 1715 scheme->stats = stats; 1716 return err; 1717 } 1718 1719 static int damon_sysfs_scheme_set_tried_regions( 1720 struct damon_sysfs_scheme *scheme) 1721 { 1722 struct damon_sysfs_scheme_regions *tried_regions = 1723 damon_sysfs_scheme_regions_alloc(); 1724 int err; 1725 1726 if (!tried_regions) 1727 return -ENOMEM; 1728 err = kobject_init_and_add(&tried_regions->kobj, 1729 &damon_sysfs_scheme_regions_ktype, &scheme->kobj, 1730 "tried_regions"); 1731 if (err) 1732 kobject_put(&tried_regions->kobj); 1733 else 1734 scheme->tried_regions = tried_regions; 1735 return err; 1736 } 1737 1738 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme) 1739 { 1740 int err; 1741 1742 err = damon_sysfs_scheme_set_access_pattern(scheme); 1743 if (err) 1744 return err; 1745 err = damon_sysfs_scheme_set_quotas(scheme); 1746 if (err) 1747 goto put_access_pattern_out; 1748 err = damon_sysfs_scheme_set_watermarks(scheme); 1749 if (err) 1750 goto put_quotas_access_pattern_out; 1751 err = damos_sysfs_set_filter_dirs(scheme); 1752 if (err) 1753 goto put_watermarks_quotas_access_pattern_out; 1754 err = damon_sysfs_scheme_set_stats(scheme); 1755 if (err) 1756 goto put_filters_watermarks_quotas_access_pattern_out; 1757 err = damon_sysfs_scheme_set_tried_regions(scheme); 1758 if (err) 1759 goto put_tried_regions_out; 1760 return 0; 1761 1762 put_tried_regions_out: 1763 kobject_put(&scheme->tried_regions->kobj); 1764 scheme->tried_regions = NULL; 1765 put_filters_watermarks_quotas_access_pattern_out: 1766 kobject_put(&scheme->ops_filters->kobj); 1767 scheme->ops_filters = NULL; 1768 kobject_put(&scheme->core_filters->kobj); 1769 scheme->core_filters = NULL; 1770 kobject_put(&scheme->filters->kobj); 1771 scheme->filters = NULL; 1772 put_watermarks_quotas_access_pattern_out: 1773 kobject_put(&scheme->watermarks->kobj); 1774 scheme->watermarks = NULL; 1775 put_quotas_access_pattern_out: 1776 kobject_put(&scheme->quotas->kobj); 1777 scheme->quotas = NULL; 1778 put_access_pattern_out: 1779 kobject_put(&scheme->access_pattern->kobj); 1780 scheme->access_pattern = NULL; 1781 return err; 1782 } 1783 1784 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme) 1785 { 1786 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 1787 kobject_put(&scheme->access_pattern->kobj); 1788 damon_sysfs_quotas_rm_dirs(scheme->quotas); 1789 kobject_put(&scheme->quotas->kobj); 1790 kobject_put(&scheme->watermarks->kobj); 1791 damon_sysfs_scheme_filters_rm_dirs(scheme->filters); 1792 kobject_put(&scheme->filters->kobj); 1793 damon_sysfs_scheme_filters_rm_dirs(scheme->core_filters); 1794 kobject_put(&scheme->core_filters->kobj); 1795 damon_sysfs_scheme_filters_rm_dirs(scheme->ops_filters); 1796 kobject_put(&scheme->ops_filters->kobj); 1797 kobject_put(&scheme->stats->kobj); 1798 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions); 1799 kobject_put(&scheme->tried_regions->kobj); 1800 } 1801 1802 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr, 1803 char *buf) 1804 { 1805 struct damon_sysfs_scheme *scheme = container_of(kobj, 1806 struct damon_sysfs_scheme, kobj); 1807 1808 return sysfs_emit(buf, "%s\n", 1809 damon_sysfs_damos_action_strs[scheme->action]); 1810 } 1811 1812 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr, 1813 const char *buf, size_t count) 1814 { 1815 struct damon_sysfs_scheme *scheme = container_of(kobj, 1816 struct damon_sysfs_scheme, kobj); 1817 enum damos_action action; 1818 1819 for (action = 0; action < NR_DAMOS_ACTIONS; action++) { 1820 if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) { 1821 scheme->action = action; 1822 return count; 1823 } 1824 } 1825 return -EINVAL; 1826 } 1827 1828 static ssize_t apply_interval_us_show(struct kobject *kobj, 1829 struct kobj_attribute *attr, char *buf) 1830 { 1831 struct damon_sysfs_scheme *scheme = container_of(kobj, 1832 struct damon_sysfs_scheme, kobj); 1833 1834 return sysfs_emit(buf, "%lu\n", scheme->apply_interval_us); 1835 } 1836 1837 static ssize_t apply_interval_us_store(struct kobject *kobj, 1838 struct kobj_attribute *attr, const char *buf, size_t count) 1839 { 1840 struct damon_sysfs_scheme *scheme = container_of(kobj, 1841 struct damon_sysfs_scheme, kobj); 1842 int err = kstrtoul(buf, 0, &scheme->apply_interval_us); 1843 1844 return err ? err : count; 1845 } 1846 1847 static ssize_t target_nid_show(struct kobject *kobj, 1848 struct kobj_attribute *attr, char *buf) 1849 { 1850 struct damon_sysfs_scheme *scheme = container_of(kobj, 1851 struct damon_sysfs_scheme, kobj); 1852 1853 return sysfs_emit(buf, "%d\n", scheme->target_nid); 1854 } 1855 1856 static ssize_t target_nid_store(struct kobject *kobj, 1857 struct kobj_attribute *attr, const char *buf, size_t count) 1858 { 1859 struct damon_sysfs_scheme *scheme = container_of(kobj, 1860 struct damon_sysfs_scheme, kobj); 1861 int err = 0; 1862 1863 /* TODO: error handling for target_nid range. */ 1864 err = kstrtoint(buf, 0, &scheme->target_nid); 1865 1866 return err ? err : count; 1867 } 1868 1869 static void damon_sysfs_scheme_release(struct kobject *kobj) 1870 { 1871 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj)); 1872 } 1873 1874 static struct kobj_attribute damon_sysfs_scheme_action_attr = 1875 __ATTR_RW_MODE(action, 0600); 1876 1877 static struct kobj_attribute damon_sysfs_scheme_apply_interval_us_attr = 1878 __ATTR_RW_MODE(apply_interval_us, 0600); 1879 1880 static struct kobj_attribute damon_sysfs_scheme_target_nid_attr = 1881 __ATTR_RW_MODE(target_nid, 0600); 1882 1883 static struct attribute *damon_sysfs_scheme_attrs[] = { 1884 &damon_sysfs_scheme_action_attr.attr, 1885 &damon_sysfs_scheme_apply_interval_us_attr.attr, 1886 &damon_sysfs_scheme_target_nid_attr.attr, 1887 NULL, 1888 }; 1889 ATTRIBUTE_GROUPS(damon_sysfs_scheme); 1890 1891 static const struct kobj_type damon_sysfs_scheme_ktype = { 1892 .release = damon_sysfs_scheme_release, 1893 .sysfs_ops = &kobj_sysfs_ops, 1894 .default_groups = damon_sysfs_scheme_groups, 1895 }; 1896 1897 /* 1898 * schemes directory 1899 */ 1900 1901 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void) 1902 { 1903 return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL); 1904 } 1905 1906 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes) 1907 { 1908 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr; 1909 int i; 1910 1911 for (i = 0; i < schemes->nr; i++) { 1912 damon_sysfs_scheme_rm_dirs(schemes_arr[i]); 1913 kobject_put(&schemes_arr[i]->kobj); 1914 } 1915 schemes->nr = 0; 1916 kfree(schemes_arr); 1917 schemes->schemes_arr = NULL; 1918 } 1919 1920 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes, 1921 int nr_schemes) 1922 { 1923 struct damon_sysfs_scheme **schemes_arr, *scheme; 1924 int err, i; 1925 1926 damon_sysfs_schemes_rm_dirs(schemes); 1927 if (!nr_schemes) 1928 return 0; 1929 1930 schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr), 1931 GFP_KERNEL | __GFP_NOWARN); 1932 if (!schemes_arr) 1933 return -ENOMEM; 1934 schemes->schemes_arr = schemes_arr; 1935 1936 for (i = 0; i < nr_schemes; i++) { 1937 /* 1938 * apply_interval_us as 0 means same to aggregation interval 1939 * (same to before-apply_interval behavior) 1940 */ 1941 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT, 0); 1942 if (!scheme) { 1943 damon_sysfs_schemes_rm_dirs(schemes); 1944 return -ENOMEM; 1945 } 1946 1947 err = kobject_init_and_add(&scheme->kobj, 1948 &damon_sysfs_scheme_ktype, &schemes->kobj, 1949 "%d", i); 1950 if (err) 1951 goto out; 1952 err = damon_sysfs_scheme_add_dirs(scheme); 1953 if (err) 1954 goto out; 1955 1956 schemes_arr[i] = scheme; 1957 schemes->nr++; 1958 } 1959 return 0; 1960 1961 out: 1962 damon_sysfs_schemes_rm_dirs(schemes); 1963 kobject_put(&scheme->kobj); 1964 return err; 1965 } 1966 1967 static ssize_t nr_schemes_show(struct kobject *kobj, 1968 struct kobj_attribute *attr, char *buf) 1969 { 1970 struct damon_sysfs_schemes *schemes = container_of(kobj, 1971 struct damon_sysfs_schemes, kobj); 1972 1973 return sysfs_emit(buf, "%d\n", schemes->nr); 1974 } 1975 1976 static ssize_t nr_schemes_store(struct kobject *kobj, 1977 struct kobj_attribute *attr, const char *buf, size_t count) 1978 { 1979 struct damon_sysfs_schemes *schemes; 1980 int nr, err = kstrtoint(buf, 0, &nr); 1981 1982 if (err) 1983 return err; 1984 if (nr < 0) 1985 return -EINVAL; 1986 1987 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj); 1988 1989 if (!mutex_trylock(&damon_sysfs_lock)) 1990 return -EBUSY; 1991 err = damon_sysfs_schemes_add_dirs(schemes, nr); 1992 mutex_unlock(&damon_sysfs_lock); 1993 if (err) 1994 return err; 1995 return count; 1996 } 1997 1998 static void damon_sysfs_schemes_release(struct kobject *kobj) 1999 { 2000 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj)); 2001 } 2002 2003 static struct kobj_attribute damon_sysfs_schemes_nr_attr = 2004 __ATTR_RW_MODE(nr_schemes, 0600); 2005 2006 static struct attribute *damon_sysfs_schemes_attrs[] = { 2007 &damon_sysfs_schemes_nr_attr.attr, 2008 NULL, 2009 }; 2010 ATTRIBUTE_GROUPS(damon_sysfs_schemes); 2011 2012 const struct kobj_type damon_sysfs_schemes_ktype = { 2013 .release = damon_sysfs_schemes_release, 2014 .sysfs_ops = &kobj_sysfs_ops, 2015 .default_groups = damon_sysfs_schemes_groups, 2016 }; 2017 2018 static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg, 2019 char *memcg_path_buf, char *path) 2020 { 2021 #ifdef CONFIG_MEMCG 2022 cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX); 2023 if (sysfs_streq(memcg_path_buf, path)) 2024 return true; 2025 #endif /* CONFIG_MEMCG */ 2026 return false; 2027 } 2028 2029 static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id) 2030 { 2031 struct mem_cgroup *memcg; 2032 char *path; 2033 bool found = false; 2034 2035 if (!memcg_path) 2036 return -EINVAL; 2037 2038 path = kmalloc(sizeof(*path) * PATH_MAX, GFP_KERNEL); 2039 if (!path) 2040 return -ENOMEM; 2041 2042 for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg; 2043 memcg = mem_cgroup_iter(NULL, memcg, NULL)) { 2044 /* skip removed memcg */ 2045 if (!mem_cgroup_id(memcg)) 2046 continue; 2047 if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) { 2048 *id = mem_cgroup_id(memcg); 2049 found = true; 2050 break; 2051 } 2052 } 2053 2054 kfree(path); 2055 return found ? 0 : -EINVAL; 2056 } 2057 2058 static int damon_sysfs_add_scheme_filters(struct damos *scheme, 2059 struct damon_sysfs_scheme_filters *sysfs_filters) 2060 { 2061 int i; 2062 2063 for (i = 0; i < sysfs_filters->nr; i++) { 2064 struct damon_sysfs_scheme_filter *sysfs_filter = 2065 sysfs_filters->filters_arr[i]; 2066 struct damos_filter *filter = 2067 damos_new_filter(sysfs_filter->type, 2068 sysfs_filter->matching, 2069 sysfs_filter->allow); 2070 int err; 2071 2072 if (!filter) 2073 return -ENOMEM; 2074 if (filter->type == DAMOS_FILTER_TYPE_MEMCG) { 2075 err = damon_sysfs_memcg_path_to_id( 2076 sysfs_filter->memcg_path, 2077 &filter->memcg_id); 2078 if (err) { 2079 damos_destroy_filter(filter); 2080 return err; 2081 } 2082 } else if (filter->type == DAMOS_FILTER_TYPE_ADDR) { 2083 if (sysfs_filter->addr_range.end < 2084 sysfs_filter->addr_range.start) { 2085 damos_destroy_filter(filter); 2086 return -EINVAL; 2087 } 2088 filter->addr_range = sysfs_filter->addr_range; 2089 } else if (filter->type == DAMOS_FILTER_TYPE_TARGET) { 2090 filter->target_idx = sysfs_filter->target_idx; 2091 } else if (filter->type == DAMOS_FILTER_TYPE_HUGEPAGE_SIZE) { 2092 if (sysfs_filter->sz_range.min > 2093 sysfs_filter->sz_range.max) { 2094 damos_destroy_filter(filter); 2095 return -EINVAL; 2096 } 2097 filter->sz_range = sysfs_filter->sz_range; 2098 } 2099 2100 damos_add_filter(scheme, filter); 2101 } 2102 return 0; 2103 } 2104 2105 static int damos_sysfs_add_quota_score( 2106 struct damos_sysfs_quota_goals *sysfs_goals, 2107 struct damos_quota *quota) 2108 { 2109 struct damos_quota_goal *goal; 2110 int i; 2111 2112 for (i = 0; i < sysfs_goals->nr; i++) { 2113 struct damos_sysfs_quota_goal *sysfs_goal = 2114 sysfs_goals->goals_arr[i]; 2115 2116 if (!sysfs_goal->target_value) 2117 continue; 2118 2119 goal = damos_new_quota_goal(sysfs_goal->metric, 2120 sysfs_goal->target_value); 2121 if (!goal) 2122 return -ENOMEM; 2123 if (sysfs_goal->metric == DAMOS_QUOTA_USER_INPUT) 2124 goal->current_value = sysfs_goal->current_value; 2125 damos_add_quota_goal(quota, goal); 2126 } 2127 return 0; 2128 } 2129 2130 int damos_sysfs_set_quota_scores(struct damon_sysfs_schemes *sysfs_schemes, 2131 struct damon_ctx *ctx) 2132 { 2133 struct damos *scheme; 2134 struct damos_quota quota = {}; 2135 int i = 0; 2136 2137 INIT_LIST_HEAD("a.goals); 2138 damon_for_each_scheme(scheme, ctx) { 2139 struct damon_sysfs_scheme *sysfs_scheme; 2140 struct damos_quota_goal *g, *g_next; 2141 int err; 2142 2143 /* user could have removed the scheme sysfs dir */ 2144 if (i >= sysfs_schemes->nr) 2145 break; 2146 2147 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 2148 err = damos_sysfs_add_quota_score(sysfs_scheme->quotas->goals, 2149 "a); 2150 if (err) { 2151 damos_for_each_quota_goal_safe(g, g_next, "a) 2152 damos_destroy_quota_goal(g); 2153 return err; 2154 } 2155 err = damos_commit_quota_goals(&scheme->quota, "a); 2156 damos_for_each_quota_goal_safe(g, g_next, "a) 2157 damos_destroy_quota_goal(g); 2158 if (err) 2159 return err; 2160 i++; 2161 } 2162 return 0; 2163 } 2164 2165 void damos_sysfs_update_effective_quotas( 2166 struct damon_sysfs_schemes *sysfs_schemes, 2167 struct damon_ctx *ctx) 2168 { 2169 struct damos *scheme; 2170 int schemes_idx = 0; 2171 2172 damon_for_each_scheme(scheme, ctx) { 2173 struct damon_sysfs_quotas *sysfs_quotas; 2174 2175 /* user could have removed the scheme sysfs dir */ 2176 if (schemes_idx >= sysfs_schemes->nr) 2177 break; 2178 2179 sysfs_quotas = 2180 sysfs_schemes->schemes_arr[schemes_idx++]->quotas; 2181 sysfs_quotas->effective_sz = scheme->quota.esz; 2182 } 2183 } 2184 2185 static struct damos *damon_sysfs_mk_scheme( 2186 struct damon_sysfs_scheme *sysfs_scheme) 2187 { 2188 struct damon_sysfs_access_pattern *access_pattern = 2189 sysfs_scheme->access_pattern; 2190 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; 2191 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; 2192 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; 2193 struct damos *scheme; 2194 int err; 2195 2196 struct damos_access_pattern pattern = { 2197 .min_sz_region = access_pattern->sz->min, 2198 .max_sz_region = access_pattern->sz->max, 2199 .min_nr_accesses = access_pattern->nr_accesses->min, 2200 .max_nr_accesses = access_pattern->nr_accesses->max, 2201 .min_age_region = access_pattern->age->min, 2202 .max_age_region = access_pattern->age->max, 2203 }; 2204 struct damos_quota quota = { 2205 .ms = sysfs_quotas->ms, 2206 .sz = sysfs_quotas->sz, 2207 .reset_interval = sysfs_quotas->reset_interval_ms, 2208 .weight_sz = sysfs_weights->sz, 2209 .weight_nr_accesses = sysfs_weights->nr_accesses, 2210 .weight_age = sysfs_weights->age, 2211 }; 2212 struct damos_watermarks wmarks = { 2213 .metric = sysfs_wmarks->metric, 2214 .interval = sysfs_wmarks->interval_us, 2215 .high = sysfs_wmarks->high, 2216 .mid = sysfs_wmarks->mid, 2217 .low = sysfs_wmarks->low, 2218 }; 2219 2220 scheme = damon_new_scheme(&pattern, sysfs_scheme->action, 2221 sysfs_scheme->apply_interval_us, "a, &wmarks, 2222 sysfs_scheme->target_nid); 2223 if (!scheme) 2224 return NULL; 2225 2226 err = damos_sysfs_add_quota_score(sysfs_quotas->goals, &scheme->quota); 2227 if (err) { 2228 damon_destroy_scheme(scheme); 2229 return NULL; 2230 } 2231 2232 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->core_filters); 2233 if (err) { 2234 damon_destroy_scheme(scheme); 2235 return NULL; 2236 } 2237 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->ops_filters); 2238 if (err) { 2239 damon_destroy_scheme(scheme); 2240 return NULL; 2241 } 2242 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->filters); 2243 if (err) { 2244 damon_destroy_scheme(scheme); 2245 return NULL; 2246 } 2247 return scheme; 2248 } 2249 2250 int damon_sysfs_add_schemes(struct damon_ctx *ctx, 2251 struct damon_sysfs_schemes *sysfs_schemes) 2252 { 2253 int i; 2254 2255 for (i = 0; i < sysfs_schemes->nr; i++) { 2256 struct damos *scheme, *next; 2257 2258 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]); 2259 if (!scheme) { 2260 damon_for_each_scheme_safe(scheme, next, ctx) 2261 damon_destroy_scheme(scheme); 2262 return -ENOMEM; 2263 } 2264 damon_add_scheme(ctx, scheme); 2265 } 2266 return 0; 2267 } 2268 2269 void damon_sysfs_schemes_update_stats( 2270 struct damon_sysfs_schemes *sysfs_schemes, 2271 struct damon_ctx *ctx) 2272 { 2273 struct damos *scheme; 2274 int schemes_idx = 0; 2275 2276 damon_for_each_scheme(scheme, ctx) { 2277 struct damon_sysfs_stats *sysfs_stats; 2278 2279 /* user could have removed the scheme sysfs dir */ 2280 if (schemes_idx >= sysfs_schemes->nr) 2281 break; 2282 2283 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats; 2284 sysfs_stats->nr_tried = scheme->stat.nr_tried; 2285 sysfs_stats->sz_tried = scheme->stat.sz_tried; 2286 sysfs_stats->nr_applied = scheme->stat.nr_applied; 2287 sysfs_stats->sz_applied = scheme->stat.sz_applied; 2288 sysfs_stats->sz_ops_filter_passed = 2289 scheme->stat.sz_ops_filter_passed; 2290 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds; 2291 } 2292 } 2293 2294 /** 2295 * damos_sysfs_populate_region_dir() - Populate a schemes tried region dir. 2296 * @sysfs_schemes: Schemes directory to populate regions directory. 2297 * @ctx: Corresponding DAMON context. 2298 * @t: DAMON target of @r. 2299 * @r: DAMON region to populate the directory for. 2300 * @s: Corresponding scheme. 2301 * @total_bytes_only: Whether the request is for bytes update only. 2302 * @sz_filter_passed: Bytes of @r that passed filters of @s. 2303 * 2304 * Called from DAMOS walk callback while holding damon_sysfs_lock. 2305 */ 2306 void damos_sysfs_populate_region_dir(struct damon_sysfs_schemes *sysfs_schemes, 2307 struct damon_ctx *ctx, struct damon_target *t, 2308 struct damon_region *r, struct damos *s, bool total_bytes_only, 2309 unsigned long sz_filter_passed) 2310 { 2311 struct damos *scheme; 2312 struct damon_sysfs_scheme_regions *sysfs_regions; 2313 struct damon_sysfs_scheme_region *region; 2314 int schemes_idx = 0; 2315 2316 damon_for_each_scheme(scheme, ctx) { 2317 if (scheme == s) 2318 break; 2319 schemes_idx++; 2320 } 2321 2322 /* user could have removed the scheme sysfs dir */ 2323 if (schemes_idx >= sysfs_schemes->nr) 2324 return; 2325 2326 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions; 2327 sysfs_regions->total_bytes += r->ar.end - r->ar.start; 2328 if (total_bytes_only) 2329 return; 2330 2331 region = damon_sysfs_scheme_region_alloc(r); 2332 if (!region) 2333 return; 2334 region->sz_filter_passed = sz_filter_passed; 2335 list_add_tail(®ion->list, &sysfs_regions->regions_list); 2336 sysfs_regions->nr_regions++; 2337 if (kobject_init_and_add(®ion->kobj, 2338 &damon_sysfs_scheme_region_ktype, 2339 &sysfs_regions->kobj, "%d", 2340 sysfs_regions->nr_regions++)) { 2341 kobject_put(®ion->kobj); 2342 } 2343 } 2344 2345 int damon_sysfs_schemes_clear_regions( 2346 struct damon_sysfs_schemes *sysfs_schemes) 2347 { 2348 int i; 2349 2350 for (i = 0; i < sysfs_schemes->nr; i++) { 2351 struct damon_sysfs_scheme *sysfs_scheme; 2352 2353 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 2354 damon_sysfs_scheme_regions_rm_dirs( 2355 sysfs_scheme->tried_regions); 2356 sysfs_scheme->tried_regions->total_bytes = 0; 2357 } 2358 return 0; 2359 } 2360