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