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