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