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