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 }; 1492 1493 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void) 1494 { 1495 return kzalloc_obj(struct damon_sysfs_quotas); 1496 } 1497 1498 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas) 1499 { 1500 struct damon_sysfs_weights *weights; 1501 struct damos_sysfs_quota_goals *goals; 1502 int err; 1503 1504 weights = damon_sysfs_weights_alloc(0, 0, 0); 1505 if (!weights) 1506 return -ENOMEM; 1507 1508 err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype, 1509 "as->kobj, "weights"); 1510 if (err) { 1511 kobject_put(&weights->kobj); 1512 return err; 1513 } 1514 quotas->weights = weights; 1515 1516 goals = damos_sysfs_quota_goals_alloc(); 1517 if (!goals) { 1518 kobject_put(&weights->kobj); 1519 return -ENOMEM; 1520 } 1521 err = kobject_init_and_add(&goals->kobj, 1522 &damos_sysfs_quota_goals_ktype, "as->kobj, 1523 "goals"); 1524 if (err) { 1525 kobject_put(&weights->kobj); 1526 kobject_put(&goals->kobj); 1527 } else { 1528 quotas->goals = goals; 1529 } 1530 1531 return err; 1532 } 1533 1534 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas) 1535 { 1536 kobject_put("as->weights->kobj); 1537 damos_sysfs_quota_goals_rm_dirs(quotas->goals); 1538 kobject_put("as->goals->kobj); 1539 } 1540 1541 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr, 1542 char *buf) 1543 { 1544 struct damon_sysfs_quotas *quotas = container_of(kobj, 1545 struct damon_sysfs_quotas, kobj); 1546 1547 return sysfs_emit(buf, "%lu\n", quotas->ms); 1548 } 1549 1550 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr, 1551 const char *buf, size_t count) 1552 { 1553 struct damon_sysfs_quotas *quotas = container_of(kobj, 1554 struct damon_sysfs_quotas, kobj); 1555 int err = kstrtoul(buf, 0, "as->ms); 1556 1557 if (err) 1558 return -EINVAL; 1559 return count; 1560 } 1561 1562 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr, 1563 char *buf) 1564 { 1565 struct damon_sysfs_quotas *quotas = container_of(kobj, 1566 struct damon_sysfs_quotas, kobj); 1567 1568 return sysfs_emit(buf, "%lu\n", quotas->sz); 1569 } 1570 1571 static ssize_t bytes_store(struct kobject *kobj, 1572 struct kobj_attribute *attr, const char *buf, size_t count) 1573 { 1574 struct damon_sysfs_quotas *quotas = container_of(kobj, 1575 struct damon_sysfs_quotas, kobj); 1576 int err = kstrtoul(buf, 0, "as->sz); 1577 1578 if (err) 1579 return -EINVAL; 1580 return count; 1581 } 1582 1583 static ssize_t reset_interval_ms_show(struct kobject *kobj, 1584 struct kobj_attribute *attr, char *buf) 1585 { 1586 struct damon_sysfs_quotas *quotas = container_of(kobj, 1587 struct damon_sysfs_quotas, kobj); 1588 1589 return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms); 1590 } 1591 1592 static ssize_t reset_interval_ms_store(struct kobject *kobj, 1593 struct kobj_attribute *attr, const char *buf, size_t count) 1594 { 1595 struct damon_sysfs_quotas *quotas = container_of(kobj, 1596 struct damon_sysfs_quotas, kobj); 1597 int err = kstrtoul(buf, 0, "as->reset_interval_ms); 1598 1599 if (err) 1600 return -EINVAL; 1601 return count; 1602 } 1603 1604 static ssize_t effective_bytes_show(struct kobject *kobj, 1605 struct kobj_attribute *attr, char *buf) 1606 { 1607 struct damon_sysfs_quotas *quotas = container_of(kobj, 1608 struct damon_sysfs_quotas, kobj); 1609 1610 return sysfs_emit(buf, "%lu\n", quotas->effective_sz); 1611 } 1612 1613 static void damon_sysfs_quotas_release(struct kobject *kobj) 1614 { 1615 kfree(container_of(kobj, struct damon_sysfs_quotas, kobj)); 1616 } 1617 1618 static struct kobj_attribute damon_sysfs_quotas_ms_attr = 1619 __ATTR_RW_MODE(ms, 0600); 1620 1621 static struct kobj_attribute damon_sysfs_quotas_sz_attr = 1622 __ATTR_RW_MODE(bytes, 0600); 1623 1624 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr = 1625 __ATTR_RW_MODE(reset_interval_ms, 0600); 1626 1627 static struct kobj_attribute damon_sysfs_quotas_effective_bytes_attr = 1628 __ATTR_RO_MODE(effective_bytes, 0400); 1629 1630 static struct attribute *damon_sysfs_quotas_attrs[] = { 1631 &damon_sysfs_quotas_ms_attr.attr, 1632 &damon_sysfs_quotas_sz_attr.attr, 1633 &damon_sysfs_quotas_reset_interval_ms_attr.attr, 1634 &damon_sysfs_quotas_effective_bytes_attr.attr, 1635 NULL, 1636 }; 1637 ATTRIBUTE_GROUPS(damon_sysfs_quotas); 1638 1639 static const struct kobj_type damon_sysfs_quotas_ktype = { 1640 .release = damon_sysfs_quotas_release, 1641 .sysfs_ops = &kobj_sysfs_ops, 1642 .default_groups = damon_sysfs_quotas_groups, 1643 }; 1644 1645 /* 1646 * access_pattern directory 1647 */ 1648 1649 struct damon_sysfs_access_pattern { 1650 struct kobject kobj; 1651 struct damon_sysfs_ul_range *sz; 1652 struct damon_sysfs_ul_range *nr_accesses; 1653 struct damon_sysfs_ul_range *age; 1654 }; 1655 1656 static 1657 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void) 1658 { 1659 struct damon_sysfs_access_pattern *access_pattern = kmalloc_obj(*access_pattern); 1660 1661 if (!access_pattern) 1662 return NULL; 1663 access_pattern->kobj = (struct kobject){}; 1664 return access_pattern; 1665 } 1666 1667 static int damon_sysfs_access_pattern_add_range_dir( 1668 struct damon_sysfs_access_pattern *access_pattern, 1669 struct damon_sysfs_ul_range **range_dir_ptr, 1670 char *name) 1671 { 1672 struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0); 1673 int err; 1674 1675 if (!range) 1676 return -ENOMEM; 1677 err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype, 1678 &access_pattern->kobj, "%s", name); 1679 if (err) 1680 kobject_put(&range->kobj); 1681 else 1682 *range_dir_ptr = range; 1683 return err; 1684 } 1685 1686 static int damon_sysfs_access_pattern_add_dirs( 1687 struct damon_sysfs_access_pattern *access_pattern) 1688 { 1689 int err; 1690 1691 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1692 &access_pattern->sz, "sz"); 1693 if (err) 1694 goto put_sz_out; 1695 1696 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1697 &access_pattern->nr_accesses, "nr_accesses"); 1698 if (err) 1699 goto put_nr_accesses_sz_out; 1700 1701 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1702 &access_pattern->age, "age"); 1703 if (err) 1704 goto put_age_nr_accesses_sz_out; 1705 return 0; 1706 1707 put_age_nr_accesses_sz_out: 1708 kobject_put(&access_pattern->age->kobj); 1709 access_pattern->age = NULL; 1710 put_nr_accesses_sz_out: 1711 kobject_put(&access_pattern->nr_accesses->kobj); 1712 access_pattern->nr_accesses = NULL; 1713 put_sz_out: 1714 kobject_put(&access_pattern->sz->kobj); 1715 access_pattern->sz = NULL; 1716 return err; 1717 } 1718 1719 static void damon_sysfs_access_pattern_rm_dirs( 1720 struct damon_sysfs_access_pattern *access_pattern) 1721 { 1722 kobject_put(&access_pattern->sz->kobj); 1723 kobject_put(&access_pattern->nr_accesses->kobj); 1724 kobject_put(&access_pattern->age->kobj); 1725 } 1726 1727 static void damon_sysfs_access_pattern_release(struct kobject *kobj) 1728 { 1729 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj)); 1730 } 1731 1732 static struct attribute *damon_sysfs_access_pattern_attrs[] = { 1733 NULL, 1734 }; 1735 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern); 1736 1737 static const struct kobj_type damon_sysfs_access_pattern_ktype = { 1738 .release = damon_sysfs_access_pattern_release, 1739 .sysfs_ops = &kobj_sysfs_ops, 1740 .default_groups = damon_sysfs_access_pattern_groups, 1741 }; 1742 1743 /* 1744 * dest (action destination) directory 1745 */ 1746 1747 struct damos_sysfs_dest { 1748 struct kobject kobj; 1749 unsigned int id; 1750 unsigned int weight; 1751 }; 1752 1753 static struct damos_sysfs_dest *damos_sysfs_dest_alloc(void) 1754 { 1755 return kzalloc_obj(struct damos_sysfs_dest); 1756 } 1757 1758 static ssize_t id_show( 1759 struct kobject *kobj, struct kobj_attribute *attr, char *buf) 1760 { 1761 struct damos_sysfs_dest *dest = container_of(kobj, 1762 struct damos_sysfs_dest, kobj); 1763 1764 return sysfs_emit(buf, "%u\n", dest->id); 1765 } 1766 1767 static ssize_t id_store(struct kobject *kobj, 1768 struct kobj_attribute *attr, const char *buf, size_t count) 1769 { 1770 struct damos_sysfs_dest *dest = container_of(kobj, 1771 struct damos_sysfs_dest, kobj); 1772 int err = kstrtouint(buf, 0, &dest->id); 1773 1774 return err ? err : count; 1775 } 1776 1777 static ssize_t weight_show( 1778 struct kobject *kobj, struct kobj_attribute *attr, char *buf) 1779 { 1780 struct damos_sysfs_dest *dest = container_of(kobj, 1781 struct damos_sysfs_dest, kobj); 1782 1783 return sysfs_emit(buf, "%u\n", dest->weight); 1784 } 1785 1786 static ssize_t weight_store(struct kobject *kobj, 1787 struct kobj_attribute *attr, const char *buf, size_t count) 1788 { 1789 struct damos_sysfs_dest *dest = container_of(kobj, 1790 struct damos_sysfs_dest, kobj); 1791 int err = kstrtouint(buf, 0, &dest->weight); 1792 1793 return err ? err : count; 1794 } 1795 1796 static void damos_sysfs_dest_release(struct kobject *kobj) 1797 { 1798 struct damos_sysfs_dest *dest = container_of(kobj, 1799 struct damos_sysfs_dest, kobj); 1800 kfree(dest); 1801 } 1802 1803 static struct kobj_attribute damos_sysfs_dest_id_attr = 1804 __ATTR_RW_MODE(id, 0600); 1805 1806 static struct kobj_attribute damos_sysfs_dest_weight_attr = 1807 __ATTR_RW_MODE(weight, 0600); 1808 1809 static struct attribute *damos_sysfs_dest_attrs[] = { 1810 &damos_sysfs_dest_id_attr.attr, 1811 &damos_sysfs_dest_weight_attr.attr, 1812 NULL, 1813 }; 1814 ATTRIBUTE_GROUPS(damos_sysfs_dest); 1815 1816 static const struct kobj_type damos_sysfs_dest_ktype = { 1817 .release = damos_sysfs_dest_release, 1818 .sysfs_ops = &kobj_sysfs_ops, 1819 .default_groups = damos_sysfs_dest_groups, 1820 }; 1821 1822 /* 1823 * dests (action destinations) directory 1824 */ 1825 1826 struct damos_sysfs_dests { 1827 struct kobject kobj; 1828 struct damos_sysfs_dest **dests_arr; 1829 int nr; 1830 }; 1831 1832 static struct damos_sysfs_dests * 1833 damos_sysfs_dests_alloc(void) 1834 { 1835 return kzalloc_obj(struct damos_sysfs_dests); 1836 } 1837 1838 static void damos_sysfs_dests_rm_dirs( 1839 struct damos_sysfs_dests *dests) 1840 { 1841 struct damos_sysfs_dest **dests_arr = dests->dests_arr; 1842 int i; 1843 1844 for (i = 0; i < dests->nr; i++) 1845 kobject_put(&dests_arr[i]->kobj); 1846 dests->nr = 0; 1847 kfree(dests_arr); 1848 dests->dests_arr = NULL; 1849 } 1850 1851 static int damos_sysfs_dests_add_dirs( 1852 struct damos_sysfs_dests *dests, int nr_dests) 1853 { 1854 struct damos_sysfs_dest **dests_arr, *dest; 1855 int err, i; 1856 1857 damos_sysfs_dests_rm_dirs(dests); 1858 if (!nr_dests) 1859 return 0; 1860 1861 dests_arr = kmalloc_objs(*dests_arr, nr_dests, 1862 GFP_KERNEL | __GFP_NOWARN); 1863 if (!dests_arr) 1864 return -ENOMEM; 1865 dests->dests_arr = dests_arr; 1866 1867 for (i = 0; i < nr_dests; i++) { 1868 dest = damos_sysfs_dest_alloc(); 1869 if (!dest) { 1870 damos_sysfs_dests_rm_dirs(dests); 1871 return -ENOMEM; 1872 } 1873 1874 err = kobject_init_and_add(&dest->kobj, 1875 &damos_sysfs_dest_ktype, 1876 &dests->kobj, "%d", i); 1877 if (err) { 1878 kobject_put(&dest->kobj); 1879 damos_sysfs_dests_rm_dirs(dests); 1880 return err; 1881 } 1882 1883 dests_arr[i] = dest; 1884 dests->nr++; 1885 } 1886 return 0; 1887 } 1888 1889 static ssize_t nr_dests_show(struct kobject *kobj, 1890 struct kobj_attribute *attr, char *buf) 1891 { 1892 struct damos_sysfs_dests *dests = container_of(kobj, 1893 struct damos_sysfs_dests, kobj); 1894 1895 return sysfs_emit(buf, "%d\n", dests->nr); 1896 } 1897 1898 static ssize_t nr_dests_store(struct kobject *kobj, 1899 struct kobj_attribute *attr, const char *buf, size_t count) 1900 { 1901 struct damos_sysfs_dests *dests; 1902 int nr, err = kstrtoint(buf, 0, &nr); 1903 1904 if (err) 1905 return err; 1906 if (nr < 0) 1907 return -EINVAL; 1908 1909 dests = container_of(kobj, struct damos_sysfs_dests, kobj); 1910 1911 if (!mutex_trylock(&damon_sysfs_lock)) 1912 return -EBUSY; 1913 err = damos_sysfs_dests_add_dirs(dests, nr); 1914 mutex_unlock(&damon_sysfs_lock); 1915 if (err) 1916 return err; 1917 1918 return count; 1919 } 1920 1921 static void damos_sysfs_dests_release(struct kobject *kobj) 1922 { 1923 kfree(container_of(kobj, struct damos_sysfs_dests, kobj)); 1924 } 1925 1926 static struct kobj_attribute damos_sysfs_dests_nr_attr = 1927 __ATTR_RW_MODE(nr_dests, 0600); 1928 1929 static struct attribute *damos_sysfs_dests_attrs[] = { 1930 &damos_sysfs_dests_nr_attr.attr, 1931 NULL, 1932 }; 1933 ATTRIBUTE_GROUPS(damos_sysfs_dests); 1934 1935 static const struct kobj_type damos_sysfs_dests_ktype = { 1936 .release = damos_sysfs_dests_release, 1937 .sysfs_ops = &kobj_sysfs_ops, 1938 .default_groups = damos_sysfs_dests_groups, 1939 }; 1940 1941 /* 1942 * scheme directory 1943 */ 1944 1945 struct damon_sysfs_scheme { 1946 struct kobject kobj; 1947 enum damos_action action; 1948 struct damon_sysfs_access_pattern *access_pattern; 1949 unsigned long apply_interval_us; 1950 struct damon_sysfs_quotas *quotas; 1951 struct damon_sysfs_watermarks *watermarks; 1952 struct damon_sysfs_scheme_filters *core_filters; 1953 struct damon_sysfs_scheme_filters *ops_filters; 1954 struct damon_sysfs_scheme_filters *filters; 1955 struct damon_sysfs_stats *stats; 1956 struct damon_sysfs_scheme_regions *tried_regions; 1957 int target_nid; 1958 struct damos_sysfs_dests *dests; 1959 }; 1960 1961 struct damos_sysfs_action_name { 1962 enum damos_action action; 1963 char *name; 1964 }; 1965 1966 static struct damos_sysfs_action_name damos_sysfs_action_names[] = { 1967 { 1968 .action = DAMOS_WILLNEED, 1969 .name = "willneed", 1970 }, 1971 { 1972 .action = DAMOS_COLD, 1973 .name = "cold", 1974 }, 1975 { 1976 .action = DAMOS_PAGEOUT, 1977 .name = "pageout", 1978 }, 1979 { 1980 .action = DAMOS_HUGEPAGE, 1981 .name = "hugepage", 1982 }, 1983 { 1984 .action = DAMOS_NOHUGEPAGE, 1985 .name = "nohugepage", 1986 }, 1987 { 1988 .action = DAMOS_LRU_PRIO, 1989 .name = "lru_prio", 1990 }, 1991 { 1992 .action = DAMOS_LRU_DEPRIO, 1993 .name = "lru_deprio", 1994 }, 1995 { 1996 .action = DAMOS_MIGRATE_HOT, 1997 .name = "migrate_hot", 1998 }, 1999 { 2000 .action = DAMOS_MIGRATE_COLD, 2001 .name = "migrate_cold", 2002 }, 2003 { 2004 .action = DAMOS_STAT, 2005 .name = "stat", 2006 }, 2007 }; 2008 2009 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc( 2010 enum damos_action action, unsigned long apply_interval_us) 2011 { 2012 struct damon_sysfs_scheme *scheme = kmalloc_obj(*scheme); 2013 2014 if (!scheme) 2015 return NULL; 2016 scheme->kobj = (struct kobject){}; 2017 scheme->action = action; 2018 scheme->apply_interval_us = apply_interval_us; 2019 scheme->target_nid = NUMA_NO_NODE; 2020 return scheme; 2021 } 2022 2023 static int damon_sysfs_scheme_set_access_pattern( 2024 struct damon_sysfs_scheme *scheme) 2025 { 2026 struct damon_sysfs_access_pattern *access_pattern; 2027 int err; 2028 2029 access_pattern = damon_sysfs_access_pattern_alloc(); 2030 if (!access_pattern) 2031 return -ENOMEM; 2032 err = kobject_init_and_add(&access_pattern->kobj, 2033 &damon_sysfs_access_pattern_ktype, &scheme->kobj, 2034 "access_pattern"); 2035 if (err) 2036 goto out; 2037 err = damon_sysfs_access_pattern_add_dirs(access_pattern); 2038 if (err) 2039 goto out; 2040 scheme->access_pattern = access_pattern; 2041 return 0; 2042 2043 out: 2044 kobject_put(&access_pattern->kobj); 2045 return err; 2046 } 2047 2048 static int damos_sysfs_set_dests(struct damon_sysfs_scheme *scheme) 2049 { 2050 struct damos_sysfs_dests *dests = damos_sysfs_dests_alloc(); 2051 int err; 2052 2053 if (!dests) 2054 return -ENOMEM; 2055 err = kobject_init_and_add(&dests->kobj, &damos_sysfs_dests_ktype, 2056 &scheme->kobj, "dests"); 2057 if (err) 2058 kobject_put(&dests->kobj); 2059 else 2060 scheme->dests = dests; 2061 return err; 2062 } 2063 2064 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme) 2065 { 2066 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc(); 2067 int err; 2068 2069 if (!quotas) 2070 return -ENOMEM; 2071 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype, 2072 &scheme->kobj, "quotas"); 2073 if (err) 2074 goto out; 2075 err = damon_sysfs_quotas_add_dirs(quotas); 2076 if (err) 2077 goto out; 2078 scheme->quotas = quotas; 2079 return 0; 2080 2081 out: 2082 kobject_put("as->kobj); 2083 return err; 2084 } 2085 2086 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme) 2087 { 2088 struct damon_sysfs_watermarks *watermarks = 2089 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0); 2090 int err; 2091 2092 if (!watermarks) 2093 return -ENOMEM; 2094 err = kobject_init_and_add(&watermarks->kobj, 2095 &damon_sysfs_watermarks_ktype, &scheme->kobj, 2096 "watermarks"); 2097 if (err) 2098 kobject_put(&watermarks->kobj); 2099 else 2100 scheme->watermarks = watermarks; 2101 return err; 2102 } 2103 2104 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme, 2105 enum damos_sysfs_filter_handle_layer layer, const char *name, 2106 struct damon_sysfs_scheme_filters **filters_ptr) 2107 { 2108 struct damon_sysfs_scheme_filters *filters = 2109 damon_sysfs_scheme_filters_alloc(layer); 2110 int err; 2111 2112 if (!filters) 2113 return -ENOMEM; 2114 err = kobject_init_and_add(&filters->kobj, 2115 &damon_sysfs_scheme_filters_ktype, &scheme->kobj, 2116 "%s", name); 2117 if (err) 2118 kobject_put(&filters->kobj); 2119 else 2120 *filters_ptr = filters; 2121 return err; 2122 } 2123 2124 static int damos_sysfs_set_filter_dirs(struct damon_sysfs_scheme *scheme) 2125 { 2126 int err; 2127 2128 err = damon_sysfs_scheme_set_filters(scheme, 2129 DAMOS_SYSFS_FILTER_HANDLE_LAYER_BOTH, "filters", 2130 &scheme->filters); 2131 if (err) 2132 return err; 2133 err = damon_sysfs_scheme_set_filters(scheme, 2134 DAMOS_SYSFS_FILTER_HANDLE_LAYER_CORE, "core_filters", 2135 &scheme->core_filters); 2136 if (err) 2137 goto put_filters_out; 2138 err = damon_sysfs_scheme_set_filters(scheme, 2139 DAMOS_SYSFS_FILTER_HANDLE_LAYER_OPS, "ops_filters", 2140 &scheme->ops_filters); 2141 if (err) 2142 goto put_core_filters_out; 2143 return 0; 2144 2145 put_core_filters_out: 2146 kobject_put(&scheme->core_filters->kobj); 2147 scheme->core_filters = NULL; 2148 put_filters_out: 2149 kobject_put(&scheme->filters->kobj); 2150 scheme->filters = NULL; 2151 return err; 2152 } 2153 2154 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme) 2155 { 2156 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc(); 2157 int err; 2158 2159 if (!stats) 2160 return -ENOMEM; 2161 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype, 2162 &scheme->kobj, "stats"); 2163 if (err) 2164 kobject_put(&stats->kobj); 2165 else 2166 scheme->stats = stats; 2167 return err; 2168 } 2169 2170 static int damon_sysfs_scheme_set_tried_regions( 2171 struct damon_sysfs_scheme *scheme) 2172 { 2173 struct damon_sysfs_scheme_regions *tried_regions = 2174 damon_sysfs_scheme_regions_alloc(); 2175 int err; 2176 2177 if (!tried_regions) 2178 return -ENOMEM; 2179 err = kobject_init_and_add(&tried_regions->kobj, 2180 &damon_sysfs_scheme_regions_ktype, &scheme->kobj, 2181 "tried_regions"); 2182 if (err) 2183 kobject_put(&tried_regions->kobj); 2184 else 2185 scheme->tried_regions = tried_regions; 2186 return err; 2187 } 2188 2189 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme) 2190 { 2191 int err; 2192 2193 err = damon_sysfs_scheme_set_access_pattern(scheme); 2194 if (err) 2195 return err; 2196 err = damos_sysfs_set_dests(scheme); 2197 if (err) 2198 goto rmdir_put_access_pattern_out; 2199 err = damon_sysfs_scheme_set_quotas(scheme); 2200 if (err) 2201 goto put_dests_out; 2202 err = damon_sysfs_scheme_set_watermarks(scheme); 2203 if (err) 2204 goto rmdir_put_quotas_access_pattern_out; 2205 err = damos_sysfs_set_filter_dirs(scheme); 2206 if (err) 2207 goto put_watermarks_quotas_access_pattern_out; 2208 err = damon_sysfs_scheme_set_stats(scheme); 2209 if (err) 2210 goto put_filters_watermarks_quotas_access_pattern_out; 2211 err = damon_sysfs_scheme_set_tried_regions(scheme); 2212 if (err) 2213 goto put_tried_regions_out; 2214 return 0; 2215 2216 put_tried_regions_out: 2217 kobject_put(&scheme->tried_regions->kobj); 2218 scheme->tried_regions = NULL; 2219 put_filters_watermarks_quotas_access_pattern_out: 2220 kobject_put(&scheme->ops_filters->kobj); 2221 scheme->ops_filters = NULL; 2222 kobject_put(&scheme->core_filters->kobj); 2223 scheme->core_filters = NULL; 2224 kobject_put(&scheme->filters->kobj); 2225 scheme->filters = NULL; 2226 put_watermarks_quotas_access_pattern_out: 2227 kobject_put(&scheme->watermarks->kobj); 2228 scheme->watermarks = NULL; 2229 rmdir_put_quotas_access_pattern_out: 2230 damon_sysfs_quotas_rm_dirs(scheme->quotas); 2231 kobject_put(&scheme->quotas->kobj); 2232 scheme->quotas = NULL; 2233 put_dests_out: 2234 kobject_put(&scheme->dests->kobj); 2235 scheme->dests = NULL; 2236 rmdir_put_access_pattern_out: 2237 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 2238 kobject_put(&scheme->access_pattern->kobj); 2239 scheme->access_pattern = NULL; 2240 return err; 2241 } 2242 2243 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme) 2244 { 2245 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 2246 kobject_put(&scheme->access_pattern->kobj); 2247 damos_sysfs_dests_rm_dirs(scheme->dests); 2248 kobject_put(&scheme->dests->kobj); 2249 damon_sysfs_quotas_rm_dirs(scheme->quotas); 2250 kobject_put(&scheme->quotas->kobj); 2251 kobject_put(&scheme->watermarks->kobj); 2252 damon_sysfs_scheme_filters_rm_dirs(scheme->filters); 2253 kobject_put(&scheme->filters->kobj); 2254 damon_sysfs_scheme_filters_rm_dirs(scheme->core_filters); 2255 kobject_put(&scheme->core_filters->kobj); 2256 damon_sysfs_scheme_filters_rm_dirs(scheme->ops_filters); 2257 kobject_put(&scheme->ops_filters->kobj); 2258 kobject_put(&scheme->stats->kobj); 2259 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions); 2260 kobject_put(&scheme->tried_regions->kobj); 2261 } 2262 2263 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr, 2264 char *buf) 2265 { 2266 struct damon_sysfs_scheme *scheme = container_of(kobj, 2267 struct damon_sysfs_scheme, kobj); 2268 int i; 2269 2270 for (i = 0; i < ARRAY_SIZE(damos_sysfs_action_names); i++) { 2271 struct damos_sysfs_action_name *action_name; 2272 2273 action_name = &damos_sysfs_action_names[i]; 2274 if (action_name->action == scheme->action) 2275 return sysfs_emit(buf, "%s\n", action_name->name); 2276 } 2277 return -EINVAL; 2278 } 2279 2280 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr, 2281 const char *buf, size_t count) 2282 { 2283 struct damon_sysfs_scheme *scheme = container_of(kobj, 2284 struct damon_sysfs_scheme, kobj); 2285 int i; 2286 2287 for (i = 0; i < ARRAY_SIZE(damos_sysfs_action_names); i++) { 2288 struct damos_sysfs_action_name *action_name; 2289 2290 action_name = &damos_sysfs_action_names[i]; 2291 if (sysfs_streq(buf, action_name->name)) { 2292 scheme->action = action_name->action; 2293 return count; 2294 } 2295 } 2296 return -EINVAL; 2297 } 2298 2299 static ssize_t apply_interval_us_show(struct kobject *kobj, 2300 struct kobj_attribute *attr, char *buf) 2301 { 2302 struct damon_sysfs_scheme *scheme = container_of(kobj, 2303 struct damon_sysfs_scheme, kobj); 2304 2305 return sysfs_emit(buf, "%lu\n", scheme->apply_interval_us); 2306 } 2307 2308 static ssize_t apply_interval_us_store(struct kobject *kobj, 2309 struct kobj_attribute *attr, const char *buf, size_t count) 2310 { 2311 struct damon_sysfs_scheme *scheme = container_of(kobj, 2312 struct damon_sysfs_scheme, kobj); 2313 int err = kstrtoul(buf, 0, &scheme->apply_interval_us); 2314 2315 return err ? err : count; 2316 } 2317 2318 static ssize_t target_nid_show(struct kobject *kobj, 2319 struct kobj_attribute *attr, char *buf) 2320 { 2321 struct damon_sysfs_scheme *scheme = container_of(kobj, 2322 struct damon_sysfs_scheme, kobj); 2323 2324 return sysfs_emit(buf, "%d\n", scheme->target_nid); 2325 } 2326 2327 static ssize_t target_nid_store(struct kobject *kobj, 2328 struct kobj_attribute *attr, const char *buf, size_t count) 2329 { 2330 struct damon_sysfs_scheme *scheme = container_of(kobj, 2331 struct damon_sysfs_scheme, kobj); 2332 int err = 0; 2333 2334 err = kstrtoint(buf, 0, &scheme->target_nid); 2335 2336 return err ? err : count; 2337 } 2338 2339 static void damon_sysfs_scheme_release(struct kobject *kobj) 2340 { 2341 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj)); 2342 } 2343 2344 static struct kobj_attribute damon_sysfs_scheme_action_attr = 2345 __ATTR_RW_MODE(action, 0600); 2346 2347 static struct kobj_attribute damon_sysfs_scheme_apply_interval_us_attr = 2348 __ATTR_RW_MODE(apply_interval_us, 0600); 2349 2350 static struct kobj_attribute damon_sysfs_scheme_target_nid_attr = 2351 __ATTR_RW_MODE(target_nid, 0600); 2352 2353 static struct attribute *damon_sysfs_scheme_attrs[] = { 2354 &damon_sysfs_scheme_action_attr.attr, 2355 &damon_sysfs_scheme_apply_interval_us_attr.attr, 2356 &damon_sysfs_scheme_target_nid_attr.attr, 2357 NULL, 2358 }; 2359 ATTRIBUTE_GROUPS(damon_sysfs_scheme); 2360 2361 static const struct kobj_type damon_sysfs_scheme_ktype = { 2362 .release = damon_sysfs_scheme_release, 2363 .sysfs_ops = &kobj_sysfs_ops, 2364 .default_groups = damon_sysfs_scheme_groups, 2365 }; 2366 2367 /* 2368 * schemes directory 2369 */ 2370 2371 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void) 2372 { 2373 return kzalloc_obj(struct damon_sysfs_schemes); 2374 } 2375 2376 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes) 2377 { 2378 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr; 2379 int i; 2380 2381 for (i = 0; i < schemes->nr; i++) { 2382 damon_sysfs_scheme_rm_dirs(schemes_arr[i]); 2383 kobject_put(&schemes_arr[i]->kobj); 2384 } 2385 schemes->nr = 0; 2386 kfree(schemes_arr); 2387 schemes->schemes_arr = NULL; 2388 } 2389 2390 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes, 2391 int nr_schemes) 2392 { 2393 struct damon_sysfs_scheme **schemes_arr, *scheme; 2394 int err, i; 2395 2396 damon_sysfs_schemes_rm_dirs(schemes); 2397 if (!nr_schemes) 2398 return 0; 2399 2400 schemes_arr = kmalloc_objs(*schemes_arr, nr_schemes, 2401 GFP_KERNEL | __GFP_NOWARN); 2402 if (!schemes_arr) 2403 return -ENOMEM; 2404 schemes->schemes_arr = schemes_arr; 2405 2406 for (i = 0; i < nr_schemes; i++) { 2407 /* 2408 * apply_interval_us as 0 means same to aggregation interval 2409 * (same to before-apply_interval behavior) 2410 */ 2411 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT, 0); 2412 if (!scheme) { 2413 damon_sysfs_schemes_rm_dirs(schemes); 2414 return -ENOMEM; 2415 } 2416 2417 err = kobject_init_and_add(&scheme->kobj, 2418 &damon_sysfs_scheme_ktype, &schemes->kobj, 2419 "%d", i); 2420 if (err) 2421 goto out; 2422 err = damon_sysfs_scheme_add_dirs(scheme); 2423 if (err) 2424 goto out; 2425 2426 schemes_arr[i] = scheme; 2427 schemes->nr++; 2428 } 2429 return 0; 2430 2431 out: 2432 damon_sysfs_schemes_rm_dirs(schemes); 2433 kobject_put(&scheme->kobj); 2434 return err; 2435 } 2436 2437 static ssize_t nr_schemes_show(struct kobject *kobj, 2438 struct kobj_attribute *attr, char *buf) 2439 { 2440 struct damon_sysfs_schemes *schemes = container_of(kobj, 2441 struct damon_sysfs_schemes, kobj); 2442 2443 return sysfs_emit(buf, "%d\n", schemes->nr); 2444 } 2445 2446 static ssize_t nr_schemes_store(struct kobject *kobj, 2447 struct kobj_attribute *attr, const char *buf, size_t count) 2448 { 2449 struct damon_sysfs_schemes *schemes; 2450 int nr, err = kstrtoint(buf, 0, &nr); 2451 2452 if (err) 2453 return err; 2454 if (nr < 0) 2455 return -EINVAL; 2456 2457 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj); 2458 2459 if (!mutex_trylock(&damon_sysfs_lock)) 2460 return -EBUSY; 2461 err = damon_sysfs_schemes_add_dirs(schemes, nr); 2462 mutex_unlock(&damon_sysfs_lock); 2463 if (err) 2464 return err; 2465 return count; 2466 } 2467 2468 static void damon_sysfs_schemes_release(struct kobject *kobj) 2469 { 2470 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj)); 2471 } 2472 2473 static struct kobj_attribute damon_sysfs_schemes_nr_attr = 2474 __ATTR_RW_MODE(nr_schemes, 0600); 2475 2476 static struct attribute *damon_sysfs_schemes_attrs[] = { 2477 &damon_sysfs_schemes_nr_attr.attr, 2478 NULL, 2479 }; 2480 ATTRIBUTE_GROUPS(damon_sysfs_schemes); 2481 2482 const struct kobj_type damon_sysfs_schemes_ktype = { 2483 .release = damon_sysfs_schemes_release, 2484 .sysfs_ops = &kobj_sysfs_ops, 2485 .default_groups = damon_sysfs_schemes_groups, 2486 }; 2487 2488 static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg, 2489 char *memcg_path_buf, char *path) 2490 { 2491 #ifdef CONFIG_MEMCG 2492 cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX); 2493 if (sysfs_streq(memcg_path_buf, path)) 2494 return true; 2495 #endif /* CONFIG_MEMCG */ 2496 return false; 2497 } 2498 2499 static int damon_sysfs_memcg_path_to_id(char *memcg_path, u64 *id) 2500 { 2501 struct mem_cgroup *memcg; 2502 char *path; 2503 bool found = false; 2504 2505 if (!memcg_path) 2506 return -EINVAL; 2507 2508 path = kmalloc_array(PATH_MAX, sizeof(*path), GFP_KERNEL); 2509 if (!path) 2510 return -ENOMEM; 2511 2512 for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg; 2513 memcg = mem_cgroup_iter(NULL, memcg, NULL)) { 2514 /* skip offlined memcg */ 2515 if (!mem_cgroup_online(memcg)) 2516 continue; 2517 if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) { 2518 *id = mem_cgroup_id(memcg); 2519 found = true; 2520 break; 2521 } 2522 } 2523 2524 kfree(path); 2525 return found ? 0 : -EINVAL; 2526 } 2527 2528 static int damon_sysfs_add_scheme_filters(struct damos *scheme, 2529 struct damon_sysfs_scheme_filters *sysfs_filters) 2530 { 2531 int i; 2532 2533 for (i = 0; i < sysfs_filters->nr; i++) { 2534 struct damon_sysfs_scheme_filter *sysfs_filter = 2535 sysfs_filters->filters_arr[i]; 2536 struct damos_filter *filter = 2537 damos_new_filter(sysfs_filter->type, 2538 sysfs_filter->matching, 2539 sysfs_filter->allow); 2540 int err; 2541 2542 if (!filter) 2543 return -ENOMEM; 2544 if (filter->type == DAMOS_FILTER_TYPE_MEMCG) { 2545 err = damon_sysfs_memcg_path_to_id( 2546 sysfs_filter->memcg_path, 2547 &filter->memcg_id); 2548 if (err) { 2549 damos_destroy_filter(filter); 2550 return err; 2551 } 2552 } else if (filter->type == DAMOS_FILTER_TYPE_ADDR) { 2553 if (sysfs_filter->addr_range.end < 2554 sysfs_filter->addr_range.start) { 2555 damos_destroy_filter(filter); 2556 return -EINVAL; 2557 } 2558 filter->addr_range = sysfs_filter->addr_range; 2559 } else if (filter->type == DAMOS_FILTER_TYPE_TARGET) { 2560 filter->target_idx = sysfs_filter->target_idx; 2561 } else if (filter->type == DAMOS_FILTER_TYPE_HUGEPAGE_SIZE) { 2562 if (sysfs_filter->sz_range.min > 2563 sysfs_filter->sz_range.max) { 2564 damos_destroy_filter(filter); 2565 return -EINVAL; 2566 } 2567 filter->sz_range = sysfs_filter->sz_range; 2568 } 2569 2570 damos_add_filter(scheme, filter); 2571 } 2572 return 0; 2573 } 2574 2575 static int damos_sysfs_add_quota_score( 2576 struct damos_sysfs_quota_goals *sysfs_goals, 2577 struct damos_quota *quota) 2578 { 2579 struct damos_quota_goal *goal; 2580 int i, err; 2581 2582 for (i = 0; i < sysfs_goals->nr; i++) { 2583 struct damos_sysfs_quota_goal *sysfs_goal = 2584 sysfs_goals->goals_arr[i]; 2585 2586 if (!sysfs_goal->target_value) 2587 continue; 2588 2589 goal = damos_new_quota_goal(sysfs_goal->metric, 2590 sysfs_goal->target_value); 2591 if (!goal) 2592 return -ENOMEM; 2593 switch (sysfs_goal->metric) { 2594 case DAMOS_QUOTA_USER_INPUT: 2595 goal->current_value = sysfs_goal->current_value; 2596 break; 2597 case DAMOS_QUOTA_NODE_MEM_USED_BP: 2598 case DAMOS_QUOTA_NODE_MEM_FREE_BP: 2599 goal->nid = sysfs_goal->nid; 2600 break; 2601 case DAMOS_QUOTA_NODE_MEMCG_USED_BP: 2602 case DAMOS_QUOTA_NODE_MEMCG_FREE_BP: 2603 err = damon_sysfs_memcg_path_to_id( 2604 sysfs_goal->path, &goal->memcg_id); 2605 if (err) { 2606 damos_destroy_quota_goal(goal); 2607 return err; 2608 } 2609 goal->nid = sysfs_goal->nid; 2610 break; 2611 default: 2612 break; 2613 } 2614 damos_add_quota_goal(quota, goal); 2615 } 2616 return 0; 2617 } 2618 2619 int damos_sysfs_set_quota_scores(struct damon_sysfs_schemes *sysfs_schemes, 2620 struct damon_ctx *ctx) 2621 { 2622 struct damos *scheme; 2623 struct damos_quota quota = {}; 2624 int i = 0; 2625 2626 INIT_LIST_HEAD("a.goals); 2627 damon_for_each_scheme(scheme, ctx) { 2628 struct damon_sysfs_scheme *sysfs_scheme; 2629 struct damos_quota_goal *g, *g_next; 2630 int err; 2631 2632 /* user could have removed the scheme sysfs dir */ 2633 if (i >= sysfs_schemes->nr) 2634 break; 2635 2636 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 2637 err = damos_sysfs_add_quota_score(sysfs_scheme->quotas->goals, 2638 "a); 2639 if (err) { 2640 damos_for_each_quota_goal_safe(g, g_next, "a) 2641 damos_destroy_quota_goal(g); 2642 return err; 2643 } 2644 err = damos_commit_quota_goals(&scheme->quota, "a); 2645 damos_for_each_quota_goal_safe(g, g_next, "a) 2646 damos_destroy_quota_goal(g); 2647 if (err) 2648 return err; 2649 i++; 2650 } 2651 return 0; 2652 } 2653 2654 void damos_sysfs_update_effective_quotas( 2655 struct damon_sysfs_schemes *sysfs_schemes, 2656 struct damon_ctx *ctx) 2657 { 2658 struct damos *scheme; 2659 int schemes_idx = 0; 2660 2661 damon_for_each_scheme(scheme, ctx) { 2662 struct damon_sysfs_quotas *sysfs_quotas; 2663 2664 /* user could have removed the scheme sysfs dir */ 2665 if (schemes_idx >= sysfs_schemes->nr) 2666 break; 2667 2668 sysfs_quotas = 2669 sysfs_schemes->schemes_arr[schemes_idx++]->quotas; 2670 sysfs_quotas->effective_sz = scheme->quota.esz; 2671 } 2672 } 2673 2674 static int damos_sysfs_add_migrate_dest(struct damos *scheme, 2675 struct damos_sysfs_dests *sysfs_dests) 2676 { 2677 struct damos_migrate_dests *dests = &scheme->migrate_dests; 2678 int i; 2679 2680 dests->node_id_arr = kmalloc_objs(*dests->node_id_arr, sysfs_dests->nr); 2681 if (!dests->node_id_arr) 2682 return -ENOMEM; 2683 dests->weight_arr = kmalloc_objs(*dests->weight_arr, sysfs_dests->nr); 2684 if (!dests->weight_arr) 2685 /* ->node_id_arr will be freed by scheme destruction */ 2686 return -ENOMEM; 2687 for (i = 0; i < sysfs_dests->nr; i++) { 2688 dests->node_id_arr[i] = sysfs_dests->dests_arr[i]->id; 2689 dests->weight_arr[i] = sysfs_dests->dests_arr[i]->weight; 2690 } 2691 dests->nr_dests = sysfs_dests->nr; 2692 return 0; 2693 } 2694 2695 static struct damos *damon_sysfs_mk_scheme( 2696 struct damon_sysfs_scheme *sysfs_scheme) 2697 { 2698 struct damon_sysfs_access_pattern *access_pattern = 2699 sysfs_scheme->access_pattern; 2700 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; 2701 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; 2702 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; 2703 struct damos *scheme; 2704 int err; 2705 2706 struct damos_access_pattern pattern = { 2707 .min_sz_region = access_pattern->sz->min, 2708 .max_sz_region = access_pattern->sz->max, 2709 .min_nr_accesses = access_pattern->nr_accesses->min, 2710 .max_nr_accesses = access_pattern->nr_accesses->max, 2711 .min_age_region = access_pattern->age->min, 2712 .max_age_region = access_pattern->age->max, 2713 }; 2714 struct damos_quota quota = { 2715 .ms = sysfs_quotas->ms, 2716 .sz = sysfs_quotas->sz, 2717 .reset_interval = sysfs_quotas->reset_interval_ms, 2718 .weight_sz = sysfs_weights->sz, 2719 .weight_nr_accesses = sysfs_weights->nr_accesses, 2720 .weight_age = sysfs_weights->age, 2721 }; 2722 struct damos_watermarks wmarks = { 2723 .metric = sysfs_wmarks->metric, 2724 .interval = sysfs_wmarks->interval_us, 2725 .high = sysfs_wmarks->high, 2726 .mid = sysfs_wmarks->mid, 2727 .low = sysfs_wmarks->low, 2728 }; 2729 2730 scheme = damon_new_scheme(&pattern, sysfs_scheme->action, 2731 sysfs_scheme->apply_interval_us, "a, &wmarks, 2732 sysfs_scheme->target_nid); 2733 if (!scheme) 2734 return NULL; 2735 2736 err = damos_sysfs_add_quota_score(sysfs_quotas->goals, &scheme->quota); 2737 if (err) { 2738 damon_destroy_scheme(scheme); 2739 return NULL; 2740 } 2741 2742 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->core_filters); 2743 if (err) { 2744 damon_destroy_scheme(scheme); 2745 return NULL; 2746 } 2747 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->ops_filters); 2748 if (err) { 2749 damon_destroy_scheme(scheme); 2750 return NULL; 2751 } 2752 err = damon_sysfs_add_scheme_filters(scheme, sysfs_scheme->filters); 2753 if (err) { 2754 damon_destroy_scheme(scheme); 2755 return NULL; 2756 } 2757 err = damos_sysfs_add_migrate_dest(scheme, sysfs_scheme->dests); 2758 if (err) { 2759 damon_destroy_scheme(scheme); 2760 return NULL; 2761 } 2762 scheme->max_nr_snapshots = sysfs_scheme->stats->max_nr_snapshots; 2763 return scheme; 2764 } 2765 2766 int damon_sysfs_add_schemes(struct damon_ctx *ctx, 2767 struct damon_sysfs_schemes *sysfs_schemes) 2768 { 2769 int i; 2770 2771 for (i = 0; i < sysfs_schemes->nr; i++) { 2772 struct damos *scheme, *next; 2773 2774 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]); 2775 if (!scheme) { 2776 damon_for_each_scheme_safe(scheme, next, ctx) 2777 damon_destroy_scheme(scheme); 2778 return -ENOMEM; 2779 } 2780 damon_add_scheme(ctx, scheme); 2781 } 2782 return 0; 2783 } 2784 2785 void damon_sysfs_schemes_update_stats( 2786 struct damon_sysfs_schemes *sysfs_schemes, 2787 struct damon_ctx *ctx) 2788 { 2789 struct damos *scheme; 2790 int schemes_idx = 0; 2791 2792 damon_for_each_scheme(scheme, ctx) { 2793 struct damon_sysfs_stats *sysfs_stats; 2794 2795 /* user could have removed the scheme sysfs dir */ 2796 if (schemes_idx >= sysfs_schemes->nr) 2797 break; 2798 2799 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats; 2800 sysfs_stats->nr_tried = scheme->stat.nr_tried; 2801 sysfs_stats->sz_tried = scheme->stat.sz_tried; 2802 sysfs_stats->nr_applied = scheme->stat.nr_applied; 2803 sysfs_stats->sz_applied = scheme->stat.sz_applied; 2804 sysfs_stats->sz_ops_filter_passed = 2805 scheme->stat.sz_ops_filter_passed; 2806 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds; 2807 sysfs_stats->nr_snapshots = scheme->stat.nr_snapshots; 2808 } 2809 } 2810 2811 /** 2812 * damos_sysfs_populate_region_dir() - Populate a schemes tried region dir. 2813 * @sysfs_schemes: Schemes directory to populate regions directory. 2814 * @ctx: Corresponding DAMON context. 2815 * @t: DAMON target of @r. 2816 * @r: DAMON region to populate the directory for. 2817 * @s: Corresponding scheme. 2818 * @total_bytes_only: Whether the request is for bytes update only. 2819 * @sz_filter_passed: Bytes of @r that passed filters of @s. 2820 * 2821 * Called from DAMOS walk callback while holding damon_sysfs_lock. 2822 */ 2823 void damos_sysfs_populate_region_dir(struct damon_sysfs_schemes *sysfs_schemes, 2824 struct damon_ctx *ctx, struct damon_target *t, 2825 struct damon_region *r, struct damos *s, bool total_bytes_only, 2826 unsigned long sz_filter_passed) 2827 { 2828 struct damos *scheme; 2829 struct damon_sysfs_scheme_regions *sysfs_regions; 2830 struct damon_sysfs_scheme_region *region; 2831 int schemes_idx = 0; 2832 2833 damon_for_each_scheme(scheme, ctx) { 2834 if (scheme == s) 2835 break; 2836 schemes_idx++; 2837 } 2838 2839 /* user could have removed the scheme sysfs dir */ 2840 if (schemes_idx >= sysfs_schemes->nr) 2841 return; 2842 2843 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions; 2844 sysfs_regions->total_bytes += r->ar.end - r->ar.start; 2845 if (total_bytes_only) 2846 return; 2847 2848 region = damon_sysfs_scheme_region_alloc(r); 2849 if (!region) 2850 return; 2851 region->sz_filter_passed = sz_filter_passed; 2852 list_add_tail(®ion->list, &sysfs_regions->regions_list); 2853 sysfs_regions->nr_regions++; 2854 if (kobject_init_and_add(®ion->kobj, 2855 &damon_sysfs_scheme_region_ktype, 2856 &sysfs_regions->kobj, "%d", 2857 sysfs_regions->nr_regions++)) { 2858 kobject_put(®ion->kobj); 2859 } 2860 } 2861 2862 int damon_sysfs_schemes_clear_regions( 2863 struct damon_sysfs_schemes *sysfs_schemes) 2864 { 2865 int i; 2866 2867 for (i = 0; i < sysfs_schemes->nr; i++) { 2868 struct damon_sysfs_scheme *sysfs_scheme; 2869 2870 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 2871 damon_sysfs_scheme_regions_rm_dirs( 2872 sysfs_scheme->tried_regions); 2873 sysfs_scheme->tried_regions->total_bytes = 0; 2874 } 2875 return 0; 2876 } 2877