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