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