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 char *path; 1003 }; 1004 1005 static struct damos_sysfs_quota_goal *damos_sysfs_quota_goal_alloc(void) 1006 { 1007 return kzalloc(sizeof(struct damos_sysfs_quota_goal), GFP_KERNEL); 1008 } 1009 1010 struct damos_sysfs_qgoal_metric_name { 1011 enum damos_quota_goal_metric metric; 1012 char *name; 1013 }; 1014 1015 static 1016 struct damos_sysfs_qgoal_metric_name damos_sysfs_qgoal_metric_names[] = { 1017 { 1018 .metric = DAMOS_QUOTA_USER_INPUT, 1019 .name = "user_input", 1020 }, 1021 { 1022 .metric = DAMOS_QUOTA_SOME_MEM_PSI_US, 1023 .name = "some_mem_psi_us", 1024 }, 1025 { 1026 .metric = DAMOS_QUOTA_NODE_MEM_USED_BP, 1027 .name = "node_mem_used_bp", 1028 }, 1029 { 1030 .metric = DAMOS_QUOTA_NODE_MEM_FREE_BP, 1031 .name = "node_mem_free_bp", 1032 }, 1033 { 1034 .metric = DAMOS_QUOTA_NODE_MEMCG_USED_BP, 1035 .name = "node_memcg_used_bp", 1036 }, 1037 { 1038 .metric = DAMOS_QUOTA_NODE_MEMCG_FREE_BP, 1039 .name = "node_memcg_free_bp", 1040 }, 1041 }; 1042 1043 static ssize_t target_metric_show(struct kobject *kobj, 1044 struct kobj_attribute *attr, char *buf) 1045 { 1046 struct damos_sysfs_quota_goal *goal = container_of(kobj, 1047 struct damos_sysfs_quota_goal, kobj); 1048 int i; 1049 1050 for (i = 0; i < ARRAY_SIZE(damos_sysfs_qgoal_metric_names); i++) { 1051 struct damos_sysfs_qgoal_metric_name *metric_name; 1052 1053 metric_name = &damos_sysfs_qgoal_metric_names[i]; 1054 if (metric_name->metric == goal->metric) 1055 return sysfs_emit(buf, "%s\n", metric_name->name); 1056 } 1057 return -EINVAL; 1058 } 1059 1060 static ssize_t target_metric_store(struct kobject *kobj, 1061 struct kobj_attribute *attr, const char *buf, size_t count) 1062 { 1063 struct damos_sysfs_quota_goal *goal = container_of(kobj, 1064 struct damos_sysfs_quota_goal, kobj); 1065 int i; 1066 1067 for (i = 0; i < ARRAY_SIZE(damos_sysfs_qgoal_metric_names); i++) { 1068 struct damos_sysfs_qgoal_metric_name *metric_name; 1069 1070 metric_name = &damos_sysfs_qgoal_metric_names[i]; 1071 if (sysfs_streq(buf, metric_name->name)) { 1072 goal->metric = metric_name->metric; 1073 return count; 1074 } 1075 } 1076 return -EINVAL; 1077 } 1078 1079 static ssize_t target_value_show(struct kobject *kobj, 1080 struct kobj_attribute *attr, char *buf) 1081 { 1082 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1083 damos_sysfs_quota_goal, kobj); 1084 1085 return sysfs_emit(buf, "%lu\n", goal->target_value); 1086 } 1087 1088 static ssize_t target_value_store(struct kobject *kobj, 1089 struct kobj_attribute *attr, const char *buf, size_t count) 1090 { 1091 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1092 damos_sysfs_quota_goal, kobj); 1093 int err = kstrtoul(buf, 0, &goal->target_value); 1094 1095 return err ? err : count; 1096 } 1097 1098 static ssize_t current_value_show(struct kobject *kobj, 1099 struct kobj_attribute *attr, char *buf) 1100 { 1101 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1102 damos_sysfs_quota_goal, kobj); 1103 1104 return sysfs_emit(buf, "%lu\n", goal->current_value); 1105 } 1106 1107 static ssize_t current_value_store(struct kobject *kobj, 1108 struct kobj_attribute *attr, const char *buf, size_t count) 1109 { 1110 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1111 damos_sysfs_quota_goal, kobj); 1112 int err = kstrtoul(buf, 0, &goal->current_value); 1113 1114 /* feed callback should check existence of this file and read value */ 1115 return err ? err : count; 1116 } 1117 1118 static ssize_t nid_show(struct kobject *kobj, 1119 struct kobj_attribute *attr, char *buf) 1120 { 1121 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1122 damos_sysfs_quota_goal, kobj); 1123 1124 1125 return sysfs_emit(buf, "%d\n", goal->nid); 1126 } 1127 1128 static ssize_t nid_store(struct kobject *kobj, 1129 struct kobj_attribute *attr, const char *buf, size_t count) 1130 { 1131 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 1132 damos_sysfs_quota_goal, kobj); 1133 int err = kstrtoint(buf, 0, &goal->nid); 1134 1135 /* feed callback should check existence of this file and read value */ 1136 return err ? err : count; 1137 } 1138 1139 static ssize_t path_show(struct kobject *kobj, 1140 struct kobj_attribute *attr, char *buf) 1141 { 1142 struct damos_sysfs_quota_goal *goal = container_of(kobj, 1143 struct damos_sysfs_quota_goal, kobj); 1144 1145 return sysfs_emit(buf, "%s\n", goal->path ? goal->path : ""); 1146 } 1147 1148 static ssize_t path_store(struct kobject *kobj, 1149 struct kobj_attribute *attr, const char *buf, size_t count) 1150 { 1151 struct damos_sysfs_quota_goal *goal = container_of(kobj, 1152 struct damos_sysfs_quota_goal, kobj); 1153 char *path = kmalloc_array(size_add(count, 1), sizeof(*path), 1154 GFP_KERNEL); 1155 1156 if (!path) 1157 return -ENOMEM; 1158 1159 strscpy(path, buf, count + 1); 1160 kfree(goal->path); 1161 goal->path = path; 1162 return count; 1163 } 1164 1165 static void damos_sysfs_quota_goal_release(struct kobject *kobj) 1166 { 1167 struct damos_sysfs_quota_goal *goal = container_of(kobj, 1168 struct damos_sysfs_quota_goal, kobj); 1169 1170 kfree(goal->path); 1171 kfree(goal); 1172 } 1173 1174 static struct kobj_attribute damos_sysfs_quota_goal_target_metric_attr = 1175 __ATTR_RW_MODE(target_metric, 0600); 1176 1177 static struct kobj_attribute damos_sysfs_quota_goal_target_value_attr = 1178 __ATTR_RW_MODE(target_value, 0600); 1179 1180 static struct kobj_attribute damos_sysfs_quota_goal_current_value_attr = 1181 __ATTR_RW_MODE(current_value, 0600); 1182 1183 static struct kobj_attribute damos_sysfs_quota_goal_nid_attr = 1184 __ATTR_RW_MODE(nid, 0600); 1185 1186 static struct kobj_attribute damos_sysfs_quota_goal_path_attr = 1187 __ATTR_RW_MODE(path, 0600); 1188 1189 static struct attribute *damos_sysfs_quota_goal_attrs[] = { 1190 &damos_sysfs_quota_goal_target_metric_attr.attr, 1191 &damos_sysfs_quota_goal_target_value_attr.attr, 1192 &damos_sysfs_quota_goal_current_value_attr.attr, 1193 &damos_sysfs_quota_goal_nid_attr.attr, 1194 &damos_sysfs_quota_goal_path_attr.attr, 1195 NULL, 1196 }; 1197 ATTRIBUTE_GROUPS(damos_sysfs_quota_goal); 1198 1199 static const struct kobj_type damos_sysfs_quota_goal_ktype = { 1200 .release = damos_sysfs_quota_goal_release, 1201 .sysfs_ops = &kobj_sysfs_ops, 1202 .default_groups = damos_sysfs_quota_goal_groups, 1203 }; 1204 1205 /* 1206 * quota goals directory 1207 */ 1208 1209 struct damos_sysfs_quota_goals { 1210 struct kobject kobj; 1211 struct damos_sysfs_quota_goal **goals_arr; /* counted by nr */ 1212 int nr; 1213 }; 1214 1215 static struct damos_sysfs_quota_goals *damos_sysfs_quota_goals_alloc(void) 1216 { 1217 return kzalloc(sizeof(struct damos_sysfs_quota_goals), GFP_KERNEL); 1218 } 1219 1220 static void damos_sysfs_quota_goals_rm_dirs( 1221 struct damos_sysfs_quota_goals *goals) 1222 { 1223 struct damos_sysfs_quota_goal **goals_arr = goals->goals_arr; 1224 int i; 1225 1226 for (i = 0; i < goals->nr; i++) 1227 kobject_put(&goals_arr[i]->kobj); 1228 goals->nr = 0; 1229 kfree(goals_arr); 1230 goals->goals_arr = NULL; 1231 } 1232 1233 static int damos_sysfs_quota_goals_add_dirs( 1234 struct damos_sysfs_quota_goals *goals, int nr_goals) 1235 { 1236 struct damos_sysfs_quota_goal **goals_arr, *goal; 1237 int err, i; 1238 1239 damos_sysfs_quota_goals_rm_dirs(goals); 1240 if (!nr_goals) 1241 return 0; 1242 1243 goals_arr = kmalloc_array(nr_goals, sizeof(*goals_arr), 1244 GFP_KERNEL | __GFP_NOWARN); 1245 if (!goals_arr) 1246 return -ENOMEM; 1247 goals->goals_arr = goals_arr; 1248 1249 for (i = 0; i < nr_goals; i++) { 1250 goal = damos_sysfs_quota_goal_alloc(); 1251 if (!goal) { 1252 damos_sysfs_quota_goals_rm_dirs(goals); 1253 return -ENOMEM; 1254 } 1255 1256 err = kobject_init_and_add(&goal->kobj, 1257 &damos_sysfs_quota_goal_ktype, &goals->kobj, 1258 "%d", i); 1259 if (err) { 1260 kobject_put(&goal->kobj); 1261 damos_sysfs_quota_goals_rm_dirs(goals); 1262 return err; 1263 } 1264 1265 goals_arr[i] = goal; 1266 goals->nr++; 1267 } 1268 return 0; 1269 } 1270 1271 static ssize_t nr_goals_show(struct kobject *kobj, 1272 struct kobj_attribute *attr, char *buf) 1273 { 1274 struct damos_sysfs_quota_goals *goals = container_of(kobj, 1275 struct damos_sysfs_quota_goals, kobj); 1276 1277 return sysfs_emit(buf, "%d\n", goals->nr); 1278 } 1279 1280 static ssize_t nr_goals_store(struct kobject *kobj, 1281 struct kobj_attribute *attr, const char *buf, size_t count) 1282 { 1283 struct damos_sysfs_quota_goals *goals; 1284 int nr, err = kstrtoint(buf, 0, &nr); 1285 1286 if (err) 1287 return err; 1288 if (nr < 0) 1289 return -EINVAL; 1290 1291 goals = container_of(kobj, struct damos_sysfs_quota_goals, kobj); 1292 1293 if (!mutex_trylock(&damon_sysfs_lock)) 1294 return -EBUSY; 1295 err = damos_sysfs_quota_goals_add_dirs(goals, nr); 1296 mutex_unlock(&damon_sysfs_lock); 1297 if (err) 1298 return err; 1299 1300 return count; 1301 } 1302 1303 static void damos_sysfs_quota_goals_release(struct kobject *kobj) 1304 { 1305 kfree(container_of(kobj, struct damos_sysfs_quota_goals, kobj)); 1306 } 1307 1308 static struct kobj_attribute damos_sysfs_quota_goals_nr_attr = 1309 __ATTR_RW_MODE(nr_goals, 0600); 1310 1311 static struct attribute *damos_sysfs_quota_goals_attrs[] = { 1312 &damos_sysfs_quota_goals_nr_attr.attr, 1313 NULL, 1314 }; 1315 ATTRIBUTE_GROUPS(damos_sysfs_quota_goals); 1316 1317 static const struct kobj_type damos_sysfs_quota_goals_ktype = { 1318 .release = damos_sysfs_quota_goals_release, 1319 .sysfs_ops = &kobj_sysfs_ops, 1320 .default_groups = damos_sysfs_quota_goals_groups, 1321 }; 1322 1323 /* 1324 * scheme/weights directory 1325 */ 1326 1327 struct damon_sysfs_weights { 1328 struct kobject kobj; 1329 unsigned int sz; 1330 unsigned int nr_accesses; 1331 unsigned int age; 1332 }; 1333 1334 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz, 1335 unsigned int nr_accesses, unsigned int age) 1336 { 1337 struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights), 1338 GFP_KERNEL); 1339 1340 if (!weights) 1341 return NULL; 1342 weights->kobj = (struct kobject){}; 1343 weights->sz = sz; 1344 weights->nr_accesses = nr_accesses; 1345 weights->age = age; 1346 return weights; 1347 } 1348 1349 static ssize_t sz_permil_show(struct kobject *kobj, 1350 struct kobj_attribute *attr, char *buf) 1351 { 1352 struct damon_sysfs_weights *weights = container_of(kobj, 1353 struct damon_sysfs_weights, kobj); 1354 1355 return sysfs_emit(buf, "%u\n", weights->sz); 1356 } 1357 1358 static ssize_t sz_permil_store(struct kobject *kobj, 1359 struct kobj_attribute *attr, const char *buf, size_t count) 1360 { 1361 struct damon_sysfs_weights *weights = container_of(kobj, 1362 struct damon_sysfs_weights, kobj); 1363 int err = kstrtouint(buf, 0, &weights->sz); 1364 1365 return err ? err : count; 1366 } 1367 1368 static ssize_t nr_accesses_permil_show(struct kobject *kobj, 1369 struct kobj_attribute *attr, char *buf) 1370 { 1371 struct damon_sysfs_weights *weights = container_of(kobj, 1372 struct damon_sysfs_weights, kobj); 1373 1374 return sysfs_emit(buf, "%u\n", weights->nr_accesses); 1375 } 1376 1377 static ssize_t nr_accesses_permil_store(struct kobject *kobj, 1378 struct kobj_attribute *attr, const char *buf, size_t count) 1379 { 1380 struct damon_sysfs_weights *weights = container_of(kobj, 1381 struct damon_sysfs_weights, kobj); 1382 int err = kstrtouint(buf, 0, &weights->nr_accesses); 1383 1384 return err ? err : count; 1385 } 1386 1387 static ssize_t age_permil_show(struct kobject *kobj, 1388 struct kobj_attribute *attr, char *buf) 1389 { 1390 struct damon_sysfs_weights *weights = container_of(kobj, 1391 struct damon_sysfs_weights, kobj); 1392 1393 return sysfs_emit(buf, "%u\n", weights->age); 1394 } 1395 1396 static ssize_t age_permil_store(struct kobject *kobj, 1397 struct kobj_attribute *attr, const char *buf, size_t count) 1398 { 1399 struct damon_sysfs_weights *weights = container_of(kobj, 1400 struct damon_sysfs_weights, kobj); 1401 int err = kstrtouint(buf, 0, &weights->age); 1402 1403 return err ? err : count; 1404 } 1405 1406 static void damon_sysfs_weights_release(struct kobject *kobj) 1407 { 1408 kfree(container_of(kobj, struct damon_sysfs_weights, kobj)); 1409 } 1410 1411 static struct kobj_attribute damon_sysfs_weights_sz_attr = 1412 __ATTR_RW_MODE(sz_permil, 0600); 1413 1414 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr = 1415 __ATTR_RW_MODE(nr_accesses_permil, 0600); 1416 1417 static struct kobj_attribute damon_sysfs_weights_age_attr = 1418 __ATTR_RW_MODE(age_permil, 0600); 1419 1420 static struct attribute *damon_sysfs_weights_attrs[] = { 1421 &damon_sysfs_weights_sz_attr.attr, 1422 &damon_sysfs_weights_nr_accesses_attr.attr, 1423 &damon_sysfs_weights_age_attr.attr, 1424 NULL, 1425 }; 1426 ATTRIBUTE_GROUPS(damon_sysfs_weights); 1427 1428 static const struct kobj_type damon_sysfs_weights_ktype = { 1429 .release = damon_sysfs_weights_release, 1430 .sysfs_ops = &kobj_sysfs_ops, 1431 .default_groups = damon_sysfs_weights_groups, 1432 }; 1433 1434 /* 1435 * quotas directory 1436 */ 1437 1438 struct damon_sysfs_quotas { 1439 struct kobject kobj; 1440 struct damon_sysfs_weights *weights; 1441 struct damos_sysfs_quota_goals *goals; 1442 unsigned long ms; 1443 unsigned long sz; 1444 unsigned long reset_interval_ms; 1445 unsigned long effective_sz; /* Effective size quota in bytes */ 1446 }; 1447 1448 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void) 1449 { 1450 return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL); 1451 } 1452 1453 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas) 1454 { 1455 struct damon_sysfs_weights *weights; 1456 struct damos_sysfs_quota_goals *goals; 1457 int err; 1458 1459 weights = damon_sysfs_weights_alloc(0, 0, 0); 1460 if (!weights) 1461 return -ENOMEM; 1462 1463 err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype, 1464 "as->kobj, "weights"); 1465 if (err) { 1466 kobject_put(&weights->kobj); 1467 return err; 1468 } 1469 quotas->weights = weights; 1470 1471 goals = damos_sysfs_quota_goals_alloc(); 1472 if (!goals) { 1473 kobject_put(&weights->kobj); 1474 return -ENOMEM; 1475 } 1476 err = kobject_init_and_add(&goals->kobj, 1477 &damos_sysfs_quota_goals_ktype, "as->kobj, 1478 "goals"); 1479 if (err) { 1480 kobject_put(&weights->kobj); 1481 kobject_put(&goals->kobj); 1482 } else { 1483 quotas->goals = goals; 1484 } 1485 1486 return err; 1487 } 1488 1489 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas) 1490 { 1491 kobject_put("as->weights->kobj); 1492 damos_sysfs_quota_goals_rm_dirs(quotas->goals); 1493 kobject_put("as->goals->kobj); 1494 } 1495 1496 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr, 1497 char *buf) 1498 { 1499 struct damon_sysfs_quotas *quotas = container_of(kobj, 1500 struct damon_sysfs_quotas, kobj); 1501 1502 return sysfs_emit(buf, "%lu\n", quotas->ms); 1503 } 1504 1505 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr, 1506 const char *buf, size_t count) 1507 { 1508 struct damon_sysfs_quotas *quotas = container_of(kobj, 1509 struct damon_sysfs_quotas, kobj); 1510 int err = kstrtoul(buf, 0, "as->ms); 1511 1512 if (err) 1513 return -EINVAL; 1514 return count; 1515 } 1516 1517 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr, 1518 char *buf) 1519 { 1520 struct damon_sysfs_quotas *quotas = container_of(kobj, 1521 struct damon_sysfs_quotas, kobj); 1522 1523 return sysfs_emit(buf, "%lu\n", quotas->sz); 1524 } 1525 1526 static ssize_t bytes_store(struct kobject *kobj, 1527 struct kobj_attribute *attr, const char *buf, size_t count) 1528 { 1529 struct damon_sysfs_quotas *quotas = container_of(kobj, 1530 struct damon_sysfs_quotas, kobj); 1531 int err = kstrtoul(buf, 0, "as->sz); 1532 1533 if (err) 1534 return -EINVAL; 1535 return count; 1536 } 1537 1538 static ssize_t reset_interval_ms_show(struct kobject *kobj, 1539 struct kobj_attribute *attr, char *buf) 1540 { 1541 struct damon_sysfs_quotas *quotas = container_of(kobj, 1542 struct damon_sysfs_quotas, kobj); 1543 1544 return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms); 1545 } 1546 1547 static ssize_t reset_interval_ms_store(struct kobject *kobj, 1548 struct kobj_attribute *attr, const char *buf, size_t count) 1549 { 1550 struct damon_sysfs_quotas *quotas = container_of(kobj, 1551 struct damon_sysfs_quotas, kobj); 1552 int err = kstrtoul(buf, 0, "as->reset_interval_ms); 1553 1554 if (err) 1555 return -EINVAL; 1556 return count; 1557 } 1558 1559 static ssize_t effective_bytes_show(struct kobject *kobj, 1560 struct kobj_attribute *attr, char *buf) 1561 { 1562 struct damon_sysfs_quotas *quotas = container_of(kobj, 1563 struct damon_sysfs_quotas, kobj); 1564 1565 return sysfs_emit(buf, "%lu\n", quotas->effective_sz); 1566 } 1567 1568 static void damon_sysfs_quotas_release(struct kobject *kobj) 1569 { 1570 kfree(container_of(kobj, struct damon_sysfs_quotas, kobj)); 1571 } 1572 1573 static struct kobj_attribute damon_sysfs_quotas_ms_attr = 1574 __ATTR_RW_MODE(ms, 0600); 1575 1576 static struct kobj_attribute damon_sysfs_quotas_sz_attr = 1577 __ATTR_RW_MODE(bytes, 0600); 1578 1579 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr = 1580 __ATTR_RW_MODE(reset_interval_ms, 0600); 1581 1582 static struct kobj_attribute damon_sysfs_quotas_effective_bytes_attr = 1583 __ATTR_RO_MODE(effective_bytes, 0400); 1584 1585 static struct attribute *damon_sysfs_quotas_attrs[] = { 1586 &damon_sysfs_quotas_ms_attr.attr, 1587 &damon_sysfs_quotas_sz_attr.attr, 1588 &damon_sysfs_quotas_reset_interval_ms_attr.attr, 1589 &damon_sysfs_quotas_effective_bytes_attr.attr, 1590 NULL, 1591 }; 1592 ATTRIBUTE_GROUPS(damon_sysfs_quotas); 1593 1594 static const struct kobj_type damon_sysfs_quotas_ktype = { 1595 .release = damon_sysfs_quotas_release, 1596 .sysfs_ops = &kobj_sysfs_ops, 1597 .default_groups = damon_sysfs_quotas_groups, 1598 }; 1599 1600 /* 1601 * access_pattern directory 1602 */ 1603 1604 struct damon_sysfs_access_pattern { 1605 struct kobject kobj; 1606 struct damon_sysfs_ul_range *sz; 1607 struct damon_sysfs_ul_range *nr_accesses; 1608 struct damon_sysfs_ul_range *age; 1609 }; 1610 1611 static 1612 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void) 1613 { 1614 struct damon_sysfs_access_pattern *access_pattern = 1615 kmalloc(sizeof(*access_pattern), GFP_KERNEL); 1616 1617 if (!access_pattern) 1618 return NULL; 1619 access_pattern->kobj = (struct kobject){}; 1620 return access_pattern; 1621 } 1622 1623 static int damon_sysfs_access_pattern_add_range_dir( 1624 struct damon_sysfs_access_pattern *access_pattern, 1625 struct damon_sysfs_ul_range **range_dir_ptr, 1626 char *name) 1627 { 1628 struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0); 1629 int err; 1630 1631 if (!range) 1632 return -ENOMEM; 1633 err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype, 1634 &access_pattern->kobj, "%s", name); 1635 if (err) 1636 kobject_put(&range->kobj); 1637 else 1638 *range_dir_ptr = range; 1639 return err; 1640 } 1641 1642 static int damon_sysfs_access_pattern_add_dirs( 1643 struct damon_sysfs_access_pattern *access_pattern) 1644 { 1645 int err; 1646 1647 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1648 &access_pattern->sz, "sz"); 1649 if (err) 1650 goto put_sz_out; 1651 1652 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1653 &access_pattern->nr_accesses, "nr_accesses"); 1654 if (err) 1655 goto put_nr_accesses_sz_out; 1656 1657 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1658 &access_pattern->age, "age"); 1659 if (err) 1660 goto put_age_nr_accesses_sz_out; 1661 return 0; 1662 1663 put_age_nr_accesses_sz_out: 1664 kobject_put(&access_pattern->age->kobj); 1665 access_pattern->age = NULL; 1666 put_nr_accesses_sz_out: 1667 kobject_put(&access_pattern->nr_accesses->kobj); 1668 access_pattern->nr_accesses = NULL; 1669 put_sz_out: 1670 kobject_put(&access_pattern->sz->kobj); 1671 access_pattern->sz = NULL; 1672 return err; 1673 } 1674 1675 static void damon_sysfs_access_pattern_rm_dirs( 1676 struct damon_sysfs_access_pattern *access_pattern) 1677 { 1678 kobject_put(&access_pattern->sz->kobj); 1679 kobject_put(&access_pattern->nr_accesses->kobj); 1680 kobject_put(&access_pattern->age->kobj); 1681 } 1682 1683 static void damon_sysfs_access_pattern_release(struct kobject *kobj) 1684 { 1685 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj)); 1686 } 1687 1688 static struct attribute *damon_sysfs_access_pattern_attrs[] = { 1689 NULL, 1690 }; 1691 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern); 1692 1693 static const struct kobj_type damon_sysfs_access_pattern_ktype = { 1694 .release = damon_sysfs_access_pattern_release, 1695 .sysfs_ops = &kobj_sysfs_ops, 1696 .default_groups = damon_sysfs_access_pattern_groups, 1697 }; 1698 1699 /* 1700 * dest (action destination) directory 1701 */ 1702 1703 struct damos_sysfs_dest { 1704 struct kobject kobj; 1705 unsigned int id; 1706 unsigned int weight; 1707 }; 1708 1709 static struct damos_sysfs_dest *damos_sysfs_dest_alloc(void) 1710 { 1711 return kzalloc(sizeof(struct damos_sysfs_dest), GFP_KERNEL); 1712 } 1713 1714 static ssize_t id_show( 1715 struct kobject *kobj, struct kobj_attribute *attr, char *buf) 1716 { 1717 struct damos_sysfs_dest *dest = container_of(kobj, 1718 struct damos_sysfs_dest, kobj); 1719 1720 return sysfs_emit(buf, "%u\n", dest->id); 1721 } 1722 1723 static ssize_t id_store(struct kobject *kobj, 1724 struct kobj_attribute *attr, const char *buf, size_t count) 1725 { 1726 struct damos_sysfs_dest *dest = container_of(kobj, 1727 struct damos_sysfs_dest, kobj); 1728 int err = kstrtouint(buf, 0, &dest->id); 1729 1730 return err ? err : count; 1731 } 1732 1733 static ssize_t weight_show( 1734 struct kobject *kobj, struct kobj_attribute *attr, char *buf) 1735 { 1736 struct damos_sysfs_dest *dest = container_of(kobj, 1737 struct damos_sysfs_dest, kobj); 1738 1739 return sysfs_emit(buf, "%u\n", dest->weight); 1740 } 1741 1742 static ssize_t weight_store(struct kobject *kobj, 1743 struct kobj_attribute *attr, const char *buf, size_t count) 1744 { 1745 struct damos_sysfs_dest *dest = container_of(kobj, 1746 struct damos_sysfs_dest, kobj); 1747 int err = kstrtouint(buf, 0, &dest->weight); 1748 1749 return err ? err : count; 1750 } 1751 1752 static void damos_sysfs_dest_release(struct kobject *kobj) 1753 { 1754 struct damos_sysfs_dest *dest = container_of(kobj, 1755 struct damos_sysfs_dest, kobj); 1756 kfree(dest); 1757 } 1758 1759 static struct kobj_attribute damos_sysfs_dest_id_attr = 1760 __ATTR_RW_MODE(id, 0600); 1761 1762 static struct kobj_attribute damos_sysfs_dest_weight_attr = 1763 __ATTR_RW_MODE(weight, 0600); 1764 1765 static struct attribute *damos_sysfs_dest_attrs[] = { 1766 &damos_sysfs_dest_id_attr.attr, 1767 &damos_sysfs_dest_weight_attr.attr, 1768 NULL, 1769 }; 1770 ATTRIBUTE_GROUPS(damos_sysfs_dest); 1771 1772 static const struct kobj_type damos_sysfs_dest_ktype = { 1773 .release = damos_sysfs_dest_release, 1774 .sysfs_ops = &kobj_sysfs_ops, 1775 .default_groups = damos_sysfs_dest_groups, 1776 }; 1777 1778 /* 1779 * dests (action destinations) directory 1780 */ 1781 1782 struct damos_sysfs_dests { 1783 struct kobject kobj; 1784 struct damos_sysfs_dest **dests_arr; 1785 int nr; 1786 }; 1787 1788 static struct damos_sysfs_dests * 1789 damos_sysfs_dests_alloc(void) 1790 { 1791 return kzalloc(sizeof(struct damos_sysfs_dests), GFP_KERNEL); 1792 } 1793 1794 static void damos_sysfs_dests_rm_dirs( 1795 struct damos_sysfs_dests *dests) 1796 { 1797 struct damos_sysfs_dest **dests_arr = dests->dests_arr; 1798 int i; 1799 1800 for (i = 0; i < dests->nr; i++) 1801 kobject_put(&dests_arr[i]->kobj); 1802 dests->nr = 0; 1803 kfree(dests_arr); 1804 dests->dests_arr = NULL; 1805 } 1806 1807 static int damos_sysfs_dests_add_dirs( 1808 struct damos_sysfs_dests *dests, int nr_dests) 1809 { 1810 struct damos_sysfs_dest **dests_arr, *dest; 1811 int err, i; 1812 1813 damos_sysfs_dests_rm_dirs(dests); 1814 if (!nr_dests) 1815 return 0; 1816 1817 dests_arr = kmalloc_array(nr_dests, sizeof(*dests_arr), 1818 GFP_KERNEL | __GFP_NOWARN); 1819 if (!dests_arr) 1820 return -ENOMEM; 1821 dests->dests_arr = dests_arr; 1822 1823 for (i = 0; i < nr_dests; i++) { 1824 dest = damos_sysfs_dest_alloc(); 1825 if (!dest) { 1826 damos_sysfs_dests_rm_dirs(dests); 1827 return -ENOMEM; 1828 } 1829 1830 err = kobject_init_and_add(&dest->kobj, 1831 &damos_sysfs_dest_ktype, 1832 &dests->kobj, "%d", i); 1833 if (err) { 1834 kobject_put(&dest->kobj); 1835 damos_sysfs_dests_rm_dirs(dests); 1836 return err; 1837 } 1838 1839 dests_arr[i] = dest; 1840 dests->nr++; 1841 } 1842 return 0; 1843 } 1844 1845 static ssize_t nr_dests_show(struct kobject *kobj, 1846 struct kobj_attribute *attr, char *buf) 1847 { 1848 struct damos_sysfs_dests *dests = container_of(kobj, 1849 struct damos_sysfs_dests, kobj); 1850 1851 return sysfs_emit(buf, "%d\n", dests->nr); 1852 } 1853 1854 static ssize_t nr_dests_store(struct kobject *kobj, 1855 struct kobj_attribute *attr, const char *buf, size_t count) 1856 { 1857 struct damos_sysfs_dests *dests; 1858 int nr, err = kstrtoint(buf, 0, &nr); 1859 1860 if (err) 1861 return err; 1862 if (nr < 0) 1863 return -EINVAL; 1864 1865 dests = container_of(kobj, struct damos_sysfs_dests, kobj); 1866 1867 if (!mutex_trylock(&damon_sysfs_lock)) 1868 return -EBUSY; 1869 err = damos_sysfs_dests_add_dirs(dests, nr); 1870 mutex_unlock(&damon_sysfs_lock); 1871 if (err) 1872 return err; 1873 1874 return count; 1875 } 1876 1877 static void damos_sysfs_dests_release(struct kobject *kobj) 1878 { 1879 kfree(container_of(kobj, struct damos_sysfs_dests, kobj)); 1880 } 1881 1882 static struct kobj_attribute damos_sysfs_dests_nr_attr = 1883 __ATTR_RW_MODE(nr_dests, 0600); 1884 1885 static struct attribute *damos_sysfs_dests_attrs[] = { 1886 &damos_sysfs_dests_nr_attr.attr, 1887 NULL, 1888 }; 1889 ATTRIBUTE_GROUPS(damos_sysfs_dests); 1890 1891 static const struct kobj_type damos_sysfs_dests_ktype = { 1892 .release = damos_sysfs_dests_release, 1893 .sysfs_ops = &kobj_sysfs_ops, 1894 .default_groups = damos_sysfs_dests_groups, 1895 }; 1896 1897 /* 1898 * scheme directory 1899 */ 1900 1901 struct damon_sysfs_scheme { 1902 struct kobject kobj; 1903 enum damos_action action; 1904 struct damon_sysfs_access_pattern *access_pattern; 1905 unsigned long apply_interval_us; 1906 struct damon_sysfs_quotas *quotas; 1907 struct damon_sysfs_watermarks *watermarks; 1908 struct damon_sysfs_scheme_filters *core_filters; 1909 struct damon_sysfs_scheme_filters *ops_filters; 1910 struct damon_sysfs_scheme_filters *filters; 1911 struct damon_sysfs_stats *stats; 1912 struct damon_sysfs_scheme_regions *tried_regions; 1913 int target_nid; 1914 struct damos_sysfs_dests *dests; 1915 }; 1916 1917 struct damos_sysfs_action_name { 1918 enum damos_action action; 1919 char *name; 1920 }; 1921 1922 static struct damos_sysfs_action_name damos_sysfs_action_names[] = { 1923 { 1924 .action = DAMOS_WILLNEED, 1925 .name = "willneed", 1926 }, 1927 { 1928 .action = DAMOS_COLD, 1929 .name = "cold", 1930 }, 1931 { 1932 .action = DAMOS_PAGEOUT, 1933 .name = "pageout", 1934 }, 1935 { 1936 .action = DAMOS_HUGEPAGE, 1937 .name = "hugepage", 1938 }, 1939 { 1940 .action = DAMOS_NOHUGEPAGE, 1941 .name = "nohugepage", 1942 }, 1943 { 1944 .action = DAMOS_LRU_PRIO, 1945 .name = "lru_prio", 1946 }, 1947 { 1948 .action = DAMOS_LRU_DEPRIO, 1949 .name = "lru_deprio", 1950 }, 1951 { 1952 .action = DAMOS_MIGRATE_HOT, 1953 .name = "migrate_hot", 1954 }, 1955 { 1956 .action = DAMOS_MIGRATE_COLD, 1957 .name = "migrate_cold", 1958 }, 1959 { 1960 .action = DAMOS_STAT, 1961 .name = "stat", 1962 }, 1963 }; 1964 1965 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc( 1966 enum damos_action action, unsigned long apply_interval_us) 1967 { 1968 struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme), 1969 GFP_KERNEL); 1970 1971 if (!scheme) 1972 return NULL; 1973 scheme->kobj = (struct kobject){}; 1974 scheme->action = action; 1975 scheme->apply_interval_us = apply_interval_us; 1976 scheme->target_nid = NUMA_NO_NODE; 1977 return scheme; 1978 } 1979 1980 static int damon_sysfs_scheme_set_access_pattern( 1981 struct damon_sysfs_scheme *scheme) 1982 { 1983 struct damon_sysfs_access_pattern *access_pattern; 1984 int err; 1985 1986 access_pattern = damon_sysfs_access_pattern_alloc(); 1987 if (!access_pattern) 1988 return -ENOMEM; 1989 err = kobject_init_and_add(&access_pattern->kobj, 1990 &damon_sysfs_access_pattern_ktype, &scheme->kobj, 1991 "access_pattern"); 1992 if (err) 1993 goto out; 1994 err = damon_sysfs_access_pattern_add_dirs(access_pattern); 1995 if (err) 1996 goto out; 1997 scheme->access_pattern = access_pattern; 1998 return 0; 1999 2000 out: 2001 kobject_put(&access_pattern->kobj); 2002 return err; 2003 } 2004 2005 static int damos_sysfs_set_dests(struct damon_sysfs_scheme *scheme) 2006 { 2007 struct damos_sysfs_dests *dests = damos_sysfs_dests_alloc(); 2008 int err; 2009 2010 if (!dests) 2011 return -ENOMEM; 2012 err = kobject_init_and_add(&dests->kobj, &damos_sysfs_dests_ktype, 2013 &scheme->kobj, "dests"); 2014 if (err) 2015 kobject_put(&dests->kobj); 2016 else 2017 scheme->dests = dests; 2018 return err; 2019 } 2020 2021 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme) 2022 { 2023 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc(); 2024 int err; 2025 2026 if (!quotas) 2027 return -ENOMEM; 2028 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype, 2029 &scheme->kobj, "quotas"); 2030 if (err) 2031 goto out; 2032 err = damon_sysfs_quotas_add_dirs(quotas); 2033 if (err) 2034 goto out; 2035 scheme->quotas = quotas; 2036 return 0; 2037 2038 out: 2039 kobject_put("as->kobj); 2040 return err; 2041 } 2042 2043 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme) 2044 { 2045 struct damon_sysfs_watermarks *watermarks = 2046 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0); 2047 int err; 2048 2049 if (!watermarks) 2050 return -ENOMEM; 2051 err = kobject_init_and_add(&watermarks->kobj, 2052 &damon_sysfs_watermarks_ktype, &scheme->kobj, 2053 "watermarks"); 2054 if (err) 2055 kobject_put(&watermarks->kobj); 2056 else 2057 scheme->watermarks = watermarks; 2058 return err; 2059 } 2060 2061 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme, 2062 enum damos_sysfs_filter_handle_layer layer, const char *name, 2063 struct damon_sysfs_scheme_filters **filters_ptr) 2064 { 2065 struct damon_sysfs_scheme_filters *filters = 2066 damon_sysfs_scheme_filters_alloc(layer); 2067 int err; 2068 2069 if (!filters) 2070 return -ENOMEM; 2071 err = kobject_init_and_add(&filters->kobj, 2072 &damon_sysfs_scheme_filters_ktype, &scheme->kobj, 2073 "%s", name); 2074 if (err) 2075 kobject_put(&filters->kobj); 2076 else 2077 *filters_ptr = filters; 2078 return err; 2079 } 2080 2081 static int damos_sysfs_set_filter_dirs(struct damon_sysfs_scheme *scheme) 2082 { 2083 int err; 2084 2085 err = damon_sysfs_scheme_set_filters(scheme, 2086 DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH, "filters", 2087 &scheme->filters); 2088 if (err) 2089 return err; 2090 err = damon_sysfs_scheme_set_filters(scheme, 2091 DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE, "core_filters", 2092 &scheme->core_filters); 2093 if (err) 2094 goto put_filters_out; 2095 err = damon_sysfs_scheme_set_filters(scheme, 2096 DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS, "ops_filters", 2097 &scheme->ops_filters); 2098 if (err) 2099 goto put_core_filters_out; 2100 return 0; 2101 2102 put_core_filters_out: 2103 kobject_put(&scheme->core_filters->kobj); 2104 scheme->core_filters = NULL; 2105 put_filters_out: 2106 kobject_put(&scheme->filters->kobj); 2107 scheme->filters = NULL; 2108 return err; 2109 } 2110 2111 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme) 2112 { 2113 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc(); 2114 int err; 2115 2116 if (!stats) 2117 return -ENOMEM; 2118 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype, 2119 &scheme->kobj, "stats"); 2120 if (err) 2121 kobject_put(&stats->kobj); 2122 else 2123 scheme->stats = stats; 2124 return err; 2125 } 2126 2127 static int damon_sysfs_scheme_set_tried_regions( 2128 struct damon_sysfs_scheme *scheme) 2129 { 2130 struct damon_sysfs_scheme_regions *tried_regions = 2131 damon_sysfs_scheme_regions_alloc(); 2132 int err; 2133 2134 if (!tried_regions) 2135 return -ENOMEM; 2136 err = kobject_init_and_add(&tried_regions->kobj, 2137 &damon_sysfs_scheme_regions_ktype, &scheme->kobj, 2138 "tried_regions"); 2139 if (err) 2140 kobject_put(&tried_regions->kobj); 2141 else 2142 scheme->tried_regions = tried_regions; 2143 return err; 2144 } 2145 2146 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme) 2147 { 2148 int err; 2149 2150 err = damon_sysfs_scheme_set_access_pattern(scheme); 2151 if (err) 2152 return err; 2153 err = damos_sysfs_set_dests(scheme); 2154 if (err) 2155 goto rmdir_put_access_pattern_out; 2156 err = damon_sysfs_scheme_set_quotas(scheme); 2157 if (err) 2158 goto put_dests_out; 2159 err = damon_sysfs_scheme_set_watermarks(scheme); 2160 if (err) 2161 goto rmdir_put_quotas_access_pattern_out; 2162 err = damos_sysfs_set_filter_dirs(scheme); 2163 if (err) 2164 goto put_watermarks_quotas_access_pattern_out; 2165 err = damon_sysfs_scheme_set_stats(scheme); 2166 if (err) 2167 goto put_filters_watermarks_quotas_access_pattern_out; 2168 err = damon_sysfs_scheme_set_tried_regions(scheme); 2169 if (err) 2170 goto put_tried_regions_out; 2171 return 0; 2172 2173 put_tried_regions_out: 2174 kobject_put(&scheme->tried_regions->kobj); 2175 scheme->tried_regions = NULL; 2176 put_filters_watermarks_quotas_access_pattern_out: 2177 kobject_put(&scheme->ops_filters->kobj); 2178 scheme->ops_filters = NULL; 2179 kobject_put(&scheme->core_filters->kobj); 2180 scheme->core_filters = NULL; 2181 kobject_put(&scheme->filters->kobj); 2182 scheme->filters = NULL; 2183 put_watermarks_quotas_access_pattern_out: 2184 kobject_put(&scheme->watermarks->kobj); 2185 scheme->watermarks = NULL; 2186 rmdir_put_quotas_access_pattern_out: 2187 damon_sysfs_quotas_rm_dirs(scheme->quotas); 2188 kobject_put(&scheme->quotas->kobj); 2189 scheme->quotas = NULL; 2190 put_dests_out: 2191 kobject_put(&scheme->dests->kobj); 2192 scheme->dests = NULL; 2193 rmdir_put_access_pattern_out: 2194 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 2195 kobject_put(&scheme->access_pattern->kobj); 2196 scheme->access_pattern = NULL; 2197 return err; 2198 } 2199 2200 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme) 2201 { 2202 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 2203 kobject_put(&scheme->access_pattern->kobj); 2204 damos_sysfs_dests_rm_dirs(scheme->dests); 2205 kobject_put(&scheme->dests->kobj); 2206 damon_sysfs_quotas_rm_dirs(scheme->quotas); 2207 kobject_put(&scheme->quotas->kobj); 2208 kobject_put(&scheme->watermarks->kobj); 2209 damon_sysfs_scheme_filters_rm_dirs(scheme->filters); 2210 kobject_put(&scheme->filters->kobj); 2211 damon_sysfs_scheme_filters_rm_dirs(scheme->core_filters); 2212 kobject_put(&scheme->core_filters->kobj); 2213 damon_sysfs_scheme_filters_rm_dirs(scheme->ops_filters); 2214 kobject_put(&scheme->ops_filters->kobj); 2215 kobject_put(&scheme->stats->kobj); 2216 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions); 2217 kobject_put(&scheme->tried_regions->kobj); 2218 } 2219 2220 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr, 2221 char *buf) 2222 { 2223 struct damon_sysfs_scheme *scheme = container_of(kobj, 2224 struct damon_sysfs_scheme, kobj); 2225 int i; 2226 2227 for (i = 0; i < ARRAY_SIZE(damos_sysfs_action_names); i++) { 2228 struct damos_sysfs_action_name *action_name; 2229 2230 action_name = &damos_sysfs_action_names[i]; 2231 if (action_name->action == scheme->action) 2232 return sysfs_emit(buf, "%s\n", action_name->name); 2233 } 2234 return -EINVAL; 2235 } 2236 2237 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr, 2238 const char *buf, size_t count) 2239 { 2240 struct damon_sysfs_scheme *scheme = container_of(kobj, 2241 struct damon_sysfs_scheme, kobj); 2242 int i; 2243 2244 for (i = 0; i < ARRAY_SIZE(damos_sysfs_action_names); i++) { 2245 struct damos_sysfs_action_name *action_name; 2246 2247 action_name = &damos_sysfs_action_names[i]; 2248 if (sysfs_streq(buf, action_name->name)) { 2249 scheme->action = action_name->action; 2250 return count; 2251 } 2252 } 2253 return -EINVAL; 2254 } 2255 2256 static ssize_t apply_interval_us_show(struct kobject *kobj, 2257 struct kobj_attribute *attr, char *buf) 2258 { 2259 struct damon_sysfs_scheme *scheme = container_of(kobj, 2260 struct damon_sysfs_scheme, kobj); 2261 2262 return sysfs_emit(buf, "%lu\n", scheme->apply_interval_us); 2263 } 2264 2265 static ssize_t apply_interval_us_store(struct kobject *kobj, 2266 struct kobj_attribute *attr, const char *buf, size_t count) 2267 { 2268 struct damon_sysfs_scheme *scheme = container_of(kobj, 2269 struct damon_sysfs_scheme, kobj); 2270 int err = kstrtoul(buf, 0, &scheme->apply_interval_us); 2271 2272 return err ? err : count; 2273 } 2274 2275 static ssize_t target_nid_show(struct kobject *kobj, 2276 struct kobj_attribute *attr, char *buf) 2277 { 2278 struct damon_sysfs_scheme *scheme = container_of(kobj, 2279 struct damon_sysfs_scheme, kobj); 2280 2281 return sysfs_emit(buf, "%d\n", scheme->target_nid); 2282 } 2283 2284 static ssize_t target_nid_store(struct kobject *kobj, 2285 struct kobj_attribute *attr, const char *buf, size_t count) 2286 { 2287 struct damon_sysfs_scheme *scheme = container_of(kobj, 2288 struct damon_sysfs_scheme, kobj); 2289 int err = 0; 2290 2291 /* TODO: error handling for target_nid range. */ 2292 err = kstrtoint(buf, 0, &scheme->target_nid); 2293 2294 return err ? err : count; 2295 } 2296 2297 static void damon_sysfs_scheme_release(struct kobject *kobj) 2298 { 2299 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj)); 2300 } 2301 2302 static struct kobj_attribute damon_sysfs_scheme_action_attr = 2303 __ATTR_RW_MODE(action, 0600); 2304 2305 static struct kobj_attribute damon_sysfs_scheme_apply_interval_us_attr = 2306 __ATTR_RW_MODE(apply_interval_us, 0600); 2307 2308 static struct kobj_attribute damon_sysfs_scheme_target_nid_attr = 2309 __ATTR_RW_MODE(target_nid, 0600); 2310 2311 static struct attribute *damon_sysfs_scheme_attrs[] = { 2312 &damon_sysfs_scheme_action_attr.attr, 2313 &damon_sysfs_scheme_apply_interval_us_attr.attr, 2314 &damon_sysfs_scheme_target_nid_attr.attr, 2315 NULL, 2316 }; 2317 ATTRIBUTE_GROUPS(damon_sysfs_scheme); 2318 2319 static const struct kobj_type damon_sysfs_scheme_ktype = { 2320 .release = damon_sysfs_scheme_release, 2321 .sysfs_ops = &kobj_sysfs_ops, 2322 .default_groups = damon_sysfs_scheme_groups, 2323 }; 2324 2325 /* 2326 * schemes directory 2327 */ 2328 2329 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void) 2330 { 2331 return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL); 2332 } 2333 2334 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes) 2335 { 2336 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr; 2337 int i; 2338 2339 for (i = 0; i < schemes->nr; i++) { 2340 damon_sysfs_scheme_rm_dirs(schemes_arr[i]); 2341 kobject_put(&schemes_arr[i]->kobj); 2342 } 2343 schemes->nr = 0; 2344 kfree(schemes_arr); 2345 schemes->schemes_arr = NULL; 2346 } 2347 2348 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes, 2349 int nr_schemes) 2350 { 2351 struct damon_sysfs_scheme **schemes_arr, *scheme; 2352 int err, i; 2353 2354 damon_sysfs_schemes_rm_dirs(schemes); 2355 if (!nr_schemes) 2356 return 0; 2357 2358 schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr), 2359 GFP_KERNEL | __GFP_NOWARN); 2360 if (!schemes_arr) 2361 return -ENOMEM; 2362 schemes->schemes_arr = schemes_arr; 2363 2364 for (i = 0; i < nr_schemes; i++) { 2365 /* 2366 * apply_interval_us as 0 means same to aggregation interval 2367 * (same to before-apply_interval behavior) 2368 */ 2369 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT, 0); 2370 if (!scheme) { 2371 damon_sysfs_schemes_rm_dirs(schemes); 2372 return -ENOMEM; 2373 } 2374 2375 err = kobject_init_and_add(&scheme->kobj, 2376 &damon_sysfs_scheme_ktype, &schemes->kobj, 2377 "%d", i); 2378 if (err) 2379 goto out; 2380 err = damon_sysfs_scheme_add_dirs(scheme); 2381 if (err) 2382 goto out; 2383 2384 schemes_arr[i] = scheme; 2385 schemes->nr++; 2386 } 2387 return 0; 2388 2389 out: 2390 damon_sysfs_schemes_rm_dirs(schemes); 2391 kobject_put(&scheme->kobj); 2392 return err; 2393 } 2394 2395 static ssize_t nr_schemes_show(struct kobject *kobj, 2396 struct kobj_attribute *attr, char *buf) 2397 { 2398 struct damon_sysfs_schemes *schemes = container_of(kobj, 2399 struct damon_sysfs_schemes, kobj); 2400 2401 return sysfs_emit(buf, "%d\n", schemes->nr); 2402 } 2403 2404 static ssize_t nr_schemes_store(struct kobject *kobj, 2405 struct kobj_attribute *attr, const char *buf, size_t count) 2406 { 2407 struct damon_sysfs_schemes *schemes; 2408 int nr, err = kstrtoint(buf, 0, &nr); 2409 2410 if (err) 2411 return err; 2412 if (nr < 0) 2413 return -EINVAL; 2414 2415 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj); 2416 2417 if (!mutex_trylock(&damon_sysfs_lock)) 2418 return -EBUSY; 2419 err = damon_sysfs_schemes_add_dirs(schemes, nr); 2420 mutex_unlock(&damon_sysfs_lock); 2421 if (err) 2422 return err; 2423 return count; 2424 } 2425 2426 static void damon_sysfs_schemes_release(struct kobject *kobj) 2427 { 2428 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj)); 2429 } 2430 2431 static struct kobj_attribute damon_sysfs_schemes_nr_attr = 2432 __ATTR_RW_MODE(nr_schemes, 0600); 2433 2434 static struct attribute *damon_sysfs_schemes_attrs[] = { 2435 &damon_sysfs_schemes_nr_attr.attr, 2436 NULL, 2437 }; 2438 ATTRIBUTE_GROUPS(damon_sysfs_schemes); 2439 2440 const struct kobj_type damon_sysfs_schemes_ktype = { 2441 .release = damon_sysfs_schemes_release, 2442 .sysfs_ops = &kobj_sysfs_ops, 2443 .default_groups = damon_sysfs_schemes_groups, 2444 }; 2445 2446 static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg, 2447 char *memcg_path_buf, char *path) 2448 { 2449 #ifdef CONFIG_MEMCG 2450 cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX); 2451 if (sysfs_streq(memcg_path_buf, path)) 2452 return true; 2453 #endif /* CONFIG_MEMCG */ 2454 return false; 2455 } 2456 2457 static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id) 2458 { 2459 struct mem_cgroup *memcg; 2460 char *path; 2461 bool found = false; 2462 2463 if (!memcg_path) 2464 return -EINVAL; 2465 2466 path = kmalloc_array(PATH_MAX, sizeof(*path), GFP_KERNEL); 2467 if (!path) 2468 return -ENOMEM; 2469 2470 for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg; 2471 memcg = mem_cgroup_iter(NULL, memcg, NULL)) { 2472 /* skip removed memcg */ 2473 if (!mem_cgroup_id(memcg)) 2474 continue; 2475 if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) { 2476 *id = mem_cgroup_id(memcg); 2477 found = true; 2478 break; 2479 } 2480 } 2481 2482 kfree(path); 2483 return found ? 0 : -EINVAL; 2484 } 2485 2486 static int damon_sysfs_add_scheme_filters(struct damos *scheme, 2487 struct damon_sysfs_scheme_filters *sysfs_filters) 2488 { 2489 int i; 2490 2491 for (i = 0; i < sysfs_filters->nr; i++) { 2492 struct damon_sysfs_scheme_filter *sysfs_filter = 2493 sysfs_filters->filters_arr[i]; 2494 struct damos_filter *filter = 2495 damos_new_filter(sysfs_filter->type, 2496 sysfs_filter->matching, 2497 sysfs_filter->allow); 2498 int err; 2499 2500 if (!filter) 2501 return -ENOMEM; 2502 if (filter->type == DAMOS_FILTER_TYPE_MEMCG) { 2503 err = damon_sysfs_memcg_path_to_id( 2504 sysfs_filter->memcg_path, 2505 &filter->memcg_id); 2506 if (err) { 2507 damos_destroy_filter(filter); 2508 return err; 2509 } 2510 } else if (filter->type == DAMOS_FILTER_TYPE_ADDR) { 2511 if (sysfs_filter->addr_range.end < 2512 sysfs_filter->addr_range.start) { 2513 damos_destroy_filter(filter); 2514 return -EINVAL; 2515 } 2516 filter->addr_range = sysfs_filter->addr_range; 2517 } else if (filter->type == DAMOS_FILTER_TYPE_TARGET) { 2518 filter->target_idx = sysfs_filter->target_idx; 2519 } else if (filter->type == DAMOS_FILTER_TYPE_HUGEPAGE_SIZE) { 2520 if (sysfs_filter->sz_range.min > 2521 sysfs_filter->sz_range.max) { 2522 damos_destroy_filter(filter); 2523 return -EINVAL; 2524 } 2525 filter->sz_range = sysfs_filter->sz_range; 2526 } 2527 2528 damos_add_filter(scheme, filter); 2529 } 2530 return 0; 2531 } 2532 2533 static int damos_sysfs_add_quota_score( 2534 struct damos_sysfs_quota_goals *sysfs_goals, 2535 struct damos_quota *quota) 2536 { 2537 struct damos_quota_goal *goal; 2538 int i, err; 2539 2540 for (i = 0; i < sysfs_goals->nr; i++) { 2541 struct damos_sysfs_quota_goal *sysfs_goal = 2542 sysfs_goals->goals_arr[i]; 2543 2544 if (!sysfs_goal->target_value) 2545 continue; 2546 2547 goal = damos_new_quota_goal(sysfs_goal->metric, 2548 sysfs_goal->target_value); 2549 if (!goal) 2550 return -ENOMEM; 2551 switch (sysfs_goal->metric) { 2552 case DAMOS_QUOTA_USER_INPUT: 2553 goal->current_value = sysfs_goal->current_value; 2554 break; 2555 case DAMOS_QUOTA_NODE_MEM_USED_BP: 2556 case DAMOS_QUOTA_NODE_MEM_FREE_BP: 2557 goal->nid = sysfs_goal->nid; 2558 break; 2559 case DAMOS_QUOTA_NODE_MEMCG_USED_BP: 2560 case DAMOS_QUOTA_NODE_MEMCG_FREE_BP: 2561 err = damon_sysfs_memcg_path_to_id( 2562 sysfs_goal->path, &goal->memcg_id); 2563 if (err) { 2564 damos_destroy_quota_goal(goal); 2565 return err; 2566 } 2567 goal->nid = sysfs_goal->nid; 2568 break; 2569 default: 2570 break; 2571 } 2572 damos_add_quota_goal(quota, goal); 2573 } 2574 return 0; 2575 } 2576 2577 int damos_sysfs_set_quota_scores(struct damon_sysfs_schemes *sysfs_schemes, 2578 struct damon_ctx *ctx) 2579 { 2580 struct damos *scheme; 2581 struct damos_quota quota = {}; 2582 int i = 0; 2583 2584 INIT_LIST_HEAD("a.goals); 2585 damon_for_each_scheme(scheme, ctx) { 2586 struct damon_sysfs_scheme *sysfs_scheme; 2587 struct damos_quota_goal *g, *g_next; 2588 int err; 2589 2590 /* user could have removed the scheme sysfs dir */ 2591 if (i >= sysfs_schemes->nr) 2592 break; 2593 2594 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 2595 err = damos_sysfs_add_quota_score(sysfs_scheme->quotas->goals, 2596 "a); 2597 if (err) { 2598 damos_for_each_quota_goal_safe(g, g_next, "a) 2599 damos_destroy_quota_goal(g); 2600 return err; 2601 } 2602 err = damos_commit_quota_goals(&scheme->quota, "a); 2603 damos_for_each_quota_goal_safe(g, g_next, "a) 2604 damos_destroy_quota_goal(g); 2605 if (err) 2606 return err; 2607 i++; 2608 } 2609 return 0; 2610 } 2611 2612 void damos_sysfs_update_effective_quotas( 2613 struct damon_sysfs_schemes *sysfs_schemes, 2614 struct damon_ctx *ctx) 2615 { 2616 struct damos *scheme; 2617 int schemes_idx = 0; 2618 2619 damon_for_each_scheme(scheme, ctx) { 2620 struct damon_sysfs_quotas *sysfs_quotas; 2621 2622 /* user could have removed the scheme sysfs dir */ 2623 if (schemes_idx >= sysfs_schemes->nr) 2624 break; 2625 2626 sysfs_quotas = 2627 sysfs_schemes->schemes_arr[schemes_idx++]->quotas; 2628 sysfs_quotas->effective_sz = scheme->quota.esz; 2629 } 2630 } 2631 2632 static int damos_sysfs_add_migrate_dest(struct damos *scheme, 2633 struct damos_sysfs_dests *sysfs_dests) 2634 { 2635 struct damos_migrate_dests *dests = &scheme->migrate_dests; 2636 int i; 2637 2638 dests->node_id_arr = kmalloc_array(sysfs_dests->nr, 2639 sizeof(*dests->node_id_arr), GFP_KERNEL); 2640 if (!dests->node_id_arr) 2641 return -ENOMEM; 2642 dests->weight_arr = kmalloc_array(sysfs_dests->nr, 2643 sizeof(*dests->weight_arr), GFP_KERNEL); 2644 if (!dests->weight_arr) 2645 /* ->node_id_arr will be freed by scheme destruction */ 2646 return -ENOMEM; 2647 for (i = 0; i < sysfs_dests->nr; i++) { 2648 dests->node_id_arr[i] = sysfs_dests->dests_arr[i]->id; 2649 dests->weight_arr[i] = sysfs_dests->dests_arr[i]->weight; 2650 } 2651 dests->nr_dests = sysfs_dests->nr; 2652 return 0; 2653 } 2654 2655 static struct damos *damon_sysfs_mk_scheme( 2656 struct damon_sysfs_scheme *sysfs_scheme) 2657 { 2658 struct damon_sysfs_access_pattern *access_pattern = 2659 sysfs_scheme->access_pattern; 2660 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; 2661 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; 2662 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; 2663 struct damos *scheme; 2664 int err; 2665 2666 struct damos_access_pattern pattern = { 2667 .min_sz_region = access_pattern->sz->min, 2668 .max_sz_region = access_pattern->sz->max, 2669 .min_nr_accesses = access_pattern->nr_accesses->min, 2670 .max_nr_accesses = access_pattern->nr_accesses->max, 2671 .min_age_region = access_pattern->age->min, 2672 .max_age_region = access_pattern->age->max, 2673 }; 2674 struct damos_quota quota = { 2675 .ms = sysfs_quotas->ms, 2676 .sz = sysfs_quotas->sz, 2677 .reset_interval = sysfs_quotas->reset_interval_ms, 2678 .weight_sz = sysfs_weights->sz, 2679 .weight_nr_accesses = sysfs_weights->nr_accesses, 2680 .weight_age = sysfs_weights->age, 2681 }; 2682 struct damos_watermarks wmarks = { 2683 .metric = sysfs_wmarks->metric, 2684 .interval = sysfs_wmarks->interval_us, 2685 .high = sysfs_wmarks->high, 2686 .mid = sysfs_wmarks->mid, 2687 .low = sysfs_wmarks->low, 2688 }; 2689 2690 scheme = damon_new_scheme(&pattern, sysfs_scheme->action, 2691 sysfs_scheme->apply_interval_us, "a, &wmarks, 2692 sysfs_scheme->target_nid); 2693 if (!scheme) 2694 return NULL; 2695 2696 err = damos_sysfs_add_quota_score(sysfs_quotas->goals, &scheme->quota); 2697 if (err) { 2698 damon_destroy_scheme(scheme); 2699 return NULL; 2700 } 2701 2702 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->core_filters); 2703 if (err) { 2704 damon_destroy_scheme(scheme); 2705 return NULL; 2706 } 2707 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->ops_filters); 2708 if (err) { 2709 damon_destroy_scheme(scheme); 2710 return NULL; 2711 } 2712 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->filters); 2713 if (err) { 2714 damon_destroy_scheme(scheme); 2715 return NULL; 2716 } 2717 err = damos_sysfs_add_migrate_dest(scheme, sysfs_scheme->dests); 2718 if (err) { 2719 damon_destroy_scheme(scheme); 2720 return NULL; 2721 } 2722 return scheme; 2723 } 2724 2725 int damon_sysfs_add_schemes(struct damon_ctx *ctx, 2726 struct damon_sysfs_schemes *sysfs_schemes) 2727 { 2728 int i; 2729 2730 for (i = 0; i < sysfs_schemes->nr; i++) { 2731 struct damos *scheme, *next; 2732 2733 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]); 2734 if (!scheme) { 2735 damon_for_each_scheme_safe(scheme, next, ctx) 2736 damon_destroy_scheme(scheme); 2737 return -ENOMEM; 2738 } 2739 damon_add_scheme(ctx, scheme); 2740 } 2741 return 0; 2742 } 2743 2744 void damon_sysfs_schemes_update_stats( 2745 struct damon_sysfs_schemes *sysfs_schemes, 2746 struct damon_ctx *ctx) 2747 { 2748 struct damos *scheme; 2749 int schemes_idx = 0; 2750 2751 damon_for_each_scheme(scheme, ctx) { 2752 struct damon_sysfs_stats *sysfs_stats; 2753 2754 /* user could have removed the scheme sysfs dir */ 2755 if (schemes_idx >= sysfs_schemes->nr) 2756 break; 2757 2758 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats; 2759 sysfs_stats->nr_tried = scheme->stat.nr_tried; 2760 sysfs_stats->sz_tried = scheme->stat.sz_tried; 2761 sysfs_stats->nr_applied = scheme->stat.nr_applied; 2762 sysfs_stats->sz_applied = scheme->stat.sz_applied; 2763 sysfs_stats->sz_ops_filter_passed = 2764 scheme->stat.sz_ops_filter_passed; 2765 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds; 2766 } 2767 } 2768 2769 /** 2770 * damos_sysfs_populate_region_dir() - Populate a schemes tried region dir. 2771 * @sysfs_schemes: Schemes directory to populate regions directory. 2772 * @ctx: Corresponding DAMON context. 2773 * @t: DAMON target of @r. 2774 * @r: DAMON region to populate the directory for. 2775 * @s: Corresponding scheme. 2776 * @total_bytes_only: Whether the request is for bytes update only. 2777 * @sz_filter_passed: Bytes of @r that passed filters of @s. 2778 * 2779 * Called from DAMOS walk callback while holding damon_sysfs_lock. 2780 */ 2781 void damos_sysfs_populate_region_dir(struct damon_sysfs_schemes *sysfs_schemes, 2782 struct damon_ctx *ctx, struct damon_target *t, 2783 struct damon_region *r, struct damos *s, bool total_bytes_only, 2784 unsigned long sz_filter_passed) 2785 { 2786 struct damos *scheme; 2787 struct damon_sysfs_scheme_regions *sysfs_regions; 2788 struct damon_sysfs_scheme_region *region; 2789 int schemes_idx = 0; 2790 2791 damon_for_each_scheme(scheme, ctx) { 2792 if (scheme == s) 2793 break; 2794 schemes_idx++; 2795 } 2796 2797 /* user could have removed the scheme sysfs dir */ 2798 if (schemes_idx >= sysfs_schemes->nr) 2799 return; 2800 2801 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions; 2802 sysfs_regions->total_bytes += r->ar.end - r->ar.start; 2803 if (total_bytes_only) 2804 return; 2805 2806 region = damon_sysfs_scheme_region_alloc(r); 2807 if (!region) 2808 return; 2809 region->sz_filter_passed = sz_filter_passed; 2810 list_add_tail(®ion->list, &sysfs_regions->regions_list); 2811 sysfs_regions->nr_regions++; 2812 if (kobject_init_and_add(®ion->kobj, 2813 &damon_sysfs_scheme_region_ktype, 2814 &sysfs_regions->kobj, "%d", 2815 sysfs_regions->nr_regions++)) { 2816 kobject_put(®ion->kobj); 2817 } 2818 } 2819 2820 int damon_sysfs_schemes_clear_regions( 2821 struct damon_sysfs_schemes *sysfs_schemes) 2822 { 2823 int i; 2824 2825 for (i = 0; i < sysfs_schemes->nr; i++) { 2826 struct damon_sysfs_scheme *sysfs_scheme; 2827 2828 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 2829 damon_sysfs_scheme_regions_rm_dirs( 2830 sysfs_scheme->tried_regions); 2831 sysfs_scheme->tried_regions->total_bytes = 0; 2832 } 2833 return 0; 2834 } 2835