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