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 10 #include "sysfs-common.h" 11 12 /* 13 * scheme region directory 14 */ 15 16 struct damon_sysfs_scheme_region { 17 struct kobject kobj; 18 struct damon_addr_range ar; 19 unsigned int nr_accesses; 20 unsigned int age; 21 struct list_head list; 22 }; 23 24 static struct damon_sysfs_scheme_region *damon_sysfs_scheme_region_alloc( 25 struct damon_region *region) 26 { 27 struct damon_sysfs_scheme_region *sysfs_region = kmalloc( 28 sizeof(*sysfs_region), GFP_KERNEL); 29 30 if (!sysfs_region) 31 return NULL; 32 sysfs_region->kobj = (struct kobject){}; 33 sysfs_region->ar = region->ar; 34 sysfs_region->nr_accesses = region->nr_accesses_bp / 10000; 35 sysfs_region->age = region->age; 36 INIT_LIST_HEAD(&sysfs_region->list); 37 return sysfs_region; 38 } 39 40 static ssize_t start_show(struct kobject *kobj, struct kobj_attribute *attr, 41 char *buf) 42 { 43 struct damon_sysfs_scheme_region *region = container_of(kobj, 44 struct damon_sysfs_scheme_region, kobj); 45 46 return sysfs_emit(buf, "%lu\n", region->ar.start); 47 } 48 49 static ssize_t end_show(struct kobject *kobj, struct kobj_attribute *attr, 50 char *buf) 51 { 52 struct damon_sysfs_scheme_region *region = container_of(kobj, 53 struct damon_sysfs_scheme_region, kobj); 54 55 return sysfs_emit(buf, "%lu\n", region->ar.end); 56 } 57 58 static ssize_t nr_accesses_show(struct kobject *kobj, 59 struct kobj_attribute *attr, char *buf) 60 { 61 struct damon_sysfs_scheme_region *region = container_of(kobj, 62 struct damon_sysfs_scheme_region, kobj); 63 64 return sysfs_emit(buf, "%u\n", region->nr_accesses); 65 } 66 67 static ssize_t age_show(struct kobject *kobj, struct kobj_attribute *attr, 68 char *buf) 69 { 70 struct damon_sysfs_scheme_region *region = container_of(kobj, 71 struct damon_sysfs_scheme_region, kobj); 72 73 return sysfs_emit(buf, "%u\n", region->age); 74 } 75 76 static void damon_sysfs_scheme_region_release(struct kobject *kobj) 77 { 78 struct damon_sysfs_scheme_region *region = container_of(kobj, 79 struct damon_sysfs_scheme_region, kobj); 80 81 list_del(®ion->list); 82 kfree(region); 83 } 84 85 static struct kobj_attribute damon_sysfs_scheme_region_start_attr = 86 __ATTR_RO_MODE(start, 0400); 87 88 static struct kobj_attribute damon_sysfs_scheme_region_end_attr = 89 __ATTR_RO_MODE(end, 0400); 90 91 static struct kobj_attribute damon_sysfs_scheme_region_nr_accesses_attr = 92 __ATTR_RO_MODE(nr_accesses, 0400); 93 94 static struct kobj_attribute damon_sysfs_scheme_region_age_attr = 95 __ATTR_RO_MODE(age, 0400); 96 97 static struct attribute *damon_sysfs_scheme_region_attrs[] = { 98 &damon_sysfs_scheme_region_start_attr.attr, 99 &damon_sysfs_scheme_region_end_attr.attr, 100 &damon_sysfs_scheme_region_nr_accesses_attr.attr, 101 &damon_sysfs_scheme_region_age_attr.attr, 102 NULL, 103 }; 104 ATTRIBUTE_GROUPS(damon_sysfs_scheme_region); 105 106 static const struct kobj_type damon_sysfs_scheme_region_ktype = { 107 .release = damon_sysfs_scheme_region_release, 108 .sysfs_ops = &kobj_sysfs_ops, 109 .default_groups = damon_sysfs_scheme_region_groups, 110 }; 111 112 /* 113 * scheme regions directory 114 */ 115 116 /* 117 * enum damos_sysfs_regions_upd_status - Represent DAMOS tried regions update 118 * status 119 * @DAMOS_TRIED_REGIONS_UPD_IDLE: Waiting for next request. 120 * @DAMOS_TRIED_REGIONS_UPD_STARTED: Update started. 121 * @DAMOS_TRIED_REGIONS_UPD_FINISHED: Update finished. 122 * 123 * Each DAMON-based operation scheme (&struct damos) has its own apply 124 * interval, and we need to expose the scheme tried regions based on only 125 * single snapshot. For this, we keep the tried regions update status for each 126 * scheme. The status becomes 'idle' at the beginning. 127 * 128 * Once the tried regions update request is received, the request handling 129 * start function (damon_sysfs_scheme_update_regions_start()) sets the status 130 * of all schemes as 'idle' again, and register ->before_damos_apply() 131 * callback. 132 * 133 * Then, the first followup ->before_damos_apply() callback 134 * (damon_sysfs_before_damos_apply()) sets the status 'started'. The first 135 * ->after_sampling() or ->after_aggregation() callback 136 * (damon_sysfs_cmd_request_callback()) after the call is called only after 137 * the scheme is completely applied to the given snapshot. Hence the callback 138 * knows the situation by showing 'started' status, and sets the status as 139 * 'finished'. Then, damon_sysfs_before_damos_apply() understands the 140 * situation by showing the 'finished' status and do nothing. 141 * 142 * If DAMOS is not applied to any region due to any reasons including the 143 * access pattern, the watermarks, the quotas, and the filters, 144 * ->before_damos_apply() will not be called back. Until the situation is 145 * changed, the update will not be finished. To avoid this, 146 * damon_sysfs_after_sampling() set the status as 'finished' if more than two 147 * apply intervals of the scheme is passed while the state is 'idle'. 148 * 149 * Finally, the tried regions request handling finisher function 150 * (damon_sysfs_schemes_update_regions_stop()) unregisters the callbacks. 151 */ 152 enum damos_sysfs_regions_upd_status { 153 DAMOS_TRIED_REGIONS_UPD_IDLE, 154 DAMOS_TRIED_REGIONS_UPD_STARTED, 155 DAMOS_TRIED_REGIONS_UPD_FINISHED, 156 }; 157 158 struct damon_sysfs_scheme_regions { 159 struct kobject kobj; 160 struct list_head regions_list; 161 int nr_regions; 162 unsigned long total_bytes; 163 enum damos_sysfs_regions_upd_status upd_status; 164 unsigned long upd_timeout_jiffies; 165 }; 166 167 static struct damon_sysfs_scheme_regions * 168 damon_sysfs_scheme_regions_alloc(void) 169 { 170 struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions), 171 GFP_KERNEL); 172 173 if (!regions) 174 return NULL; 175 176 regions->kobj = (struct kobject){}; 177 INIT_LIST_HEAD(®ions->regions_list); 178 regions->nr_regions = 0; 179 regions->total_bytes = 0; 180 regions->upd_status = DAMOS_TRIED_REGIONS_UPD_IDLE; 181 return regions; 182 } 183 184 static ssize_t total_bytes_show(struct kobject *kobj, 185 struct kobj_attribute *attr, char *buf) 186 { 187 struct damon_sysfs_scheme_regions *regions = container_of(kobj, 188 struct damon_sysfs_scheme_regions, kobj); 189 190 return sysfs_emit(buf, "%lu\n", regions->total_bytes); 191 } 192 193 static void damon_sysfs_scheme_regions_rm_dirs( 194 struct damon_sysfs_scheme_regions *regions) 195 { 196 struct damon_sysfs_scheme_region *r, *next; 197 198 list_for_each_entry_safe(r, next, ®ions->regions_list, list) { 199 /* release function deletes it from the list */ 200 kobject_put(&r->kobj); 201 regions->nr_regions--; 202 } 203 } 204 205 static void damon_sysfs_scheme_regions_release(struct kobject *kobj) 206 { 207 kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj)); 208 } 209 210 static struct kobj_attribute damon_sysfs_scheme_regions_total_bytes_attr = 211 __ATTR_RO_MODE(total_bytes, 0400); 212 213 static struct attribute *damon_sysfs_scheme_regions_attrs[] = { 214 &damon_sysfs_scheme_regions_total_bytes_attr.attr, 215 NULL, 216 }; 217 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions); 218 219 static const struct kobj_type damon_sysfs_scheme_regions_ktype = { 220 .release = damon_sysfs_scheme_regions_release, 221 .sysfs_ops = &kobj_sysfs_ops, 222 .default_groups = damon_sysfs_scheme_regions_groups, 223 }; 224 225 /* 226 * schemes/stats directory 227 */ 228 229 struct damon_sysfs_stats { 230 struct kobject kobj; 231 unsigned long nr_tried; 232 unsigned long sz_tried; 233 unsigned long nr_applied; 234 unsigned long sz_applied; 235 unsigned long qt_exceeds; 236 }; 237 238 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void) 239 { 240 return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL); 241 } 242 243 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr, 244 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->nr_tried); 250 } 251 252 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr, 253 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_tried); 259 } 260 261 static ssize_t nr_applied_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->nr_applied); 268 } 269 270 static ssize_t sz_applied_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->sz_applied); 277 } 278 279 static ssize_t qt_exceeds_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->qt_exceeds); 286 } 287 288 static void damon_sysfs_stats_release(struct kobject *kobj) 289 { 290 kfree(container_of(kobj, struct damon_sysfs_stats, kobj)); 291 } 292 293 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr = 294 __ATTR_RO_MODE(nr_tried, 0400); 295 296 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr = 297 __ATTR_RO_MODE(sz_tried, 0400); 298 299 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr = 300 __ATTR_RO_MODE(nr_applied, 0400); 301 302 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr = 303 __ATTR_RO_MODE(sz_applied, 0400); 304 305 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr = 306 __ATTR_RO_MODE(qt_exceeds, 0400); 307 308 static struct attribute *damon_sysfs_stats_attrs[] = { 309 &damon_sysfs_stats_nr_tried_attr.attr, 310 &damon_sysfs_stats_sz_tried_attr.attr, 311 &damon_sysfs_stats_nr_applied_attr.attr, 312 &damon_sysfs_stats_sz_applied_attr.attr, 313 &damon_sysfs_stats_qt_exceeds_attr.attr, 314 NULL, 315 }; 316 ATTRIBUTE_GROUPS(damon_sysfs_stats); 317 318 static const struct kobj_type damon_sysfs_stats_ktype = { 319 .release = damon_sysfs_stats_release, 320 .sysfs_ops = &kobj_sysfs_ops, 321 .default_groups = damon_sysfs_stats_groups, 322 }; 323 324 /* 325 * filter directory 326 */ 327 328 struct damon_sysfs_scheme_filter { 329 struct kobject kobj; 330 enum damos_filter_type type; 331 bool matching; 332 char *memcg_path; 333 struct damon_addr_range addr_range; 334 int target_idx; 335 }; 336 337 static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc(void) 338 { 339 return kzalloc(sizeof(struct damon_sysfs_scheme_filter), GFP_KERNEL); 340 } 341 342 /* Should match with enum damos_filter_type */ 343 static const char * const damon_sysfs_scheme_filter_type_strs[] = { 344 "anon", 345 "memcg", 346 "addr", 347 "target", 348 }; 349 350 static ssize_t type_show(struct kobject *kobj, 351 struct kobj_attribute *attr, char *buf) 352 { 353 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 354 struct damon_sysfs_scheme_filter, kobj); 355 356 return sysfs_emit(buf, "%s\n", 357 damon_sysfs_scheme_filter_type_strs[filter->type]); 358 } 359 360 static ssize_t type_store(struct kobject *kobj, 361 struct kobj_attribute *attr, const char *buf, size_t count) 362 { 363 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 364 struct damon_sysfs_scheme_filter, kobj); 365 enum damos_filter_type type; 366 ssize_t ret = -EINVAL; 367 368 for (type = 0; type < NR_DAMOS_FILTER_TYPES; type++) { 369 if (sysfs_streq(buf, damon_sysfs_scheme_filter_type_strs[ 370 type])) { 371 filter->type = type; 372 ret = count; 373 break; 374 } 375 } 376 return ret; 377 } 378 379 static ssize_t matching_show(struct kobject *kobj, 380 struct kobj_attribute *attr, char *buf) 381 { 382 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 383 struct damon_sysfs_scheme_filter, kobj); 384 385 return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N'); 386 } 387 388 static ssize_t matching_store(struct kobject *kobj, 389 struct kobj_attribute *attr, const char *buf, size_t count) 390 { 391 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 392 struct damon_sysfs_scheme_filter, kobj); 393 bool matching; 394 int err = kstrtobool(buf, &matching); 395 396 if (err) 397 return err; 398 399 filter->matching = matching; 400 return count; 401 } 402 403 static ssize_t memcg_path_show(struct kobject *kobj, 404 struct kobj_attribute *attr, char *buf) 405 { 406 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 407 struct damon_sysfs_scheme_filter, kobj); 408 409 return sysfs_emit(buf, "%s\n", 410 filter->memcg_path ? filter->memcg_path : ""); 411 } 412 413 static ssize_t memcg_path_store(struct kobject *kobj, 414 struct kobj_attribute *attr, const char *buf, size_t count) 415 { 416 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 417 struct damon_sysfs_scheme_filter, kobj); 418 char *path = kmalloc(sizeof(*path) * (count + 1), GFP_KERNEL); 419 420 if (!path) 421 return -ENOMEM; 422 423 strscpy(path, buf, count + 1); 424 filter->memcg_path = path; 425 return count; 426 } 427 428 static ssize_t addr_start_show(struct kobject *kobj, 429 struct kobj_attribute *attr, char *buf) 430 { 431 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 432 struct damon_sysfs_scheme_filter, kobj); 433 434 return sysfs_emit(buf, "%lu\n", filter->addr_range.start); 435 } 436 437 static ssize_t addr_start_store(struct kobject *kobj, 438 struct kobj_attribute *attr, const char *buf, size_t count) 439 { 440 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 441 struct damon_sysfs_scheme_filter, kobj); 442 int err = kstrtoul(buf, 0, &filter->addr_range.start); 443 444 return err ? err : count; 445 } 446 447 static ssize_t addr_end_show(struct kobject *kobj, 448 struct kobj_attribute *attr, char *buf) 449 { 450 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 451 struct damon_sysfs_scheme_filter, kobj); 452 453 return sysfs_emit(buf, "%lu\n", filter->addr_range.end); 454 } 455 456 static ssize_t addr_end_store(struct kobject *kobj, 457 struct kobj_attribute *attr, const char *buf, size_t count) 458 { 459 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 460 struct damon_sysfs_scheme_filter, kobj); 461 int err = kstrtoul(buf, 0, &filter->addr_range.end); 462 463 return err ? err : count; 464 } 465 466 static ssize_t damon_target_idx_show(struct kobject *kobj, 467 struct kobj_attribute *attr, char *buf) 468 { 469 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 470 struct damon_sysfs_scheme_filter, kobj); 471 472 return sysfs_emit(buf, "%d\n", filter->target_idx); 473 } 474 475 static ssize_t damon_target_idx_store(struct kobject *kobj, 476 struct kobj_attribute *attr, const char *buf, size_t count) 477 { 478 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 479 struct damon_sysfs_scheme_filter, kobj); 480 int err = kstrtoint(buf, 0, &filter->target_idx); 481 482 return err ? err : count; 483 } 484 485 static void damon_sysfs_scheme_filter_release(struct kobject *kobj) 486 { 487 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 488 struct damon_sysfs_scheme_filter, kobj); 489 490 kfree(filter->memcg_path); 491 kfree(filter); 492 } 493 494 static struct kobj_attribute damon_sysfs_scheme_filter_type_attr = 495 __ATTR_RW_MODE(type, 0600); 496 497 static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr = 498 __ATTR_RW_MODE(matching, 0600); 499 500 static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr = 501 __ATTR_RW_MODE(memcg_path, 0600); 502 503 static struct kobj_attribute damon_sysfs_scheme_filter_addr_start_attr = 504 __ATTR_RW_MODE(addr_start, 0600); 505 506 static struct kobj_attribute damon_sysfs_scheme_filter_addr_end_attr = 507 __ATTR_RW_MODE(addr_end, 0600); 508 509 static struct kobj_attribute damon_sysfs_scheme_filter_damon_target_idx_attr = 510 __ATTR_RW_MODE(damon_target_idx, 0600); 511 512 static struct attribute *damon_sysfs_scheme_filter_attrs[] = { 513 &damon_sysfs_scheme_filter_type_attr.attr, 514 &damon_sysfs_scheme_filter_matching_attr.attr, 515 &damon_sysfs_scheme_filter_memcg_path_attr.attr, 516 &damon_sysfs_scheme_filter_addr_start_attr.attr, 517 &damon_sysfs_scheme_filter_addr_end_attr.attr, 518 &damon_sysfs_scheme_filter_damon_target_idx_attr.attr, 519 NULL, 520 }; 521 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter); 522 523 static const struct kobj_type damon_sysfs_scheme_filter_ktype = { 524 .release = damon_sysfs_scheme_filter_release, 525 .sysfs_ops = &kobj_sysfs_ops, 526 .default_groups = damon_sysfs_scheme_filter_groups, 527 }; 528 529 /* 530 * filters directory 531 */ 532 533 struct damon_sysfs_scheme_filters { 534 struct kobject kobj; 535 struct damon_sysfs_scheme_filter **filters_arr; 536 int nr; 537 }; 538 539 static struct damon_sysfs_scheme_filters * 540 damon_sysfs_scheme_filters_alloc(void) 541 { 542 return kzalloc(sizeof(struct damon_sysfs_scheme_filters), GFP_KERNEL); 543 } 544 545 static void damon_sysfs_scheme_filters_rm_dirs( 546 struct damon_sysfs_scheme_filters *filters) 547 { 548 struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr; 549 int i; 550 551 for (i = 0; i < filters->nr; i++) 552 kobject_put(&filters_arr[i]->kobj); 553 filters->nr = 0; 554 kfree(filters_arr); 555 filters->filters_arr = NULL; 556 } 557 558 static int damon_sysfs_scheme_filters_add_dirs( 559 struct damon_sysfs_scheme_filters *filters, int nr_filters) 560 { 561 struct damon_sysfs_scheme_filter **filters_arr, *filter; 562 int err, i; 563 564 damon_sysfs_scheme_filters_rm_dirs(filters); 565 if (!nr_filters) 566 return 0; 567 568 filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr), 569 GFP_KERNEL | __GFP_NOWARN); 570 if (!filters_arr) 571 return -ENOMEM; 572 filters->filters_arr = filters_arr; 573 574 for (i = 0; i < nr_filters; i++) { 575 filter = damon_sysfs_scheme_filter_alloc(); 576 if (!filter) { 577 damon_sysfs_scheme_filters_rm_dirs(filters); 578 return -ENOMEM; 579 } 580 581 err = kobject_init_and_add(&filter->kobj, 582 &damon_sysfs_scheme_filter_ktype, 583 &filters->kobj, "%d", i); 584 if (err) { 585 kobject_put(&filter->kobj); 586 damon_sysfs_scheme_filters_rm_dirs(filters); 587 return err; 588 } 589 590 filters_arr[i] = filter; 591 filters->nr++; 592 } 593 return 0; 594 } 595 596 static ssize_t nr_filters_show(struct kobject *kobj, 597 struct kobj_attribute *attr, char *buf) 598 { 599 struct damon_sysfs_scheme_filters *filters = container_of(kobj, 600 struct damon_sysfs_scheme_filters, kobj); 601 602 return sysfs_emit(buf, "%d\n", filters->nr); 603 } 604 605 static ssize_t nr_filters_store(struct kobject *kobj, 606 struct kobj_attribute *attr, const char *buf, size_t count) 607 { 608 struct damon_sysfs_scheme_filters *filters; 609 int nr, err = kstrtoint(buf, 0, &nr); 610 611 if (err) 612 return err; 613 if (nr < 0) 614 return -EINVAL; 615 616 filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj); 617 618 if (!mutex_trylock(&damon_sysfs_lock)) 619 return -EBUSY; 620 err = damon_sysfs_scheme_filters_add_dirs(filters, nr); 621 mutex_unlock(&damon_sysfs_lock); 622 if (err) 623 return err; 624 625 return count; 626 } 627 628 static void damon_sysfs_scheme_filters_release(struct kobject *kobj) 629 { 630 kfree(container_of(kobj, struct damon_sysfs_scheme_filters, kobj)); 631 } 632 633 static struct kobj_attribute damon_sysfs_scheme_filters_nr_attr = 634 __ATTR_RW_MODE(nr_filters, 0600); 635 636 static struct attribute *damon_sysfs_scheme_filters_attrs[] = { 637 &damon_sysfs_scheme_filters_nr_attr.attr, 638 NULL, 639 }; 640 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filters); 641 642 static const struct kobj_type damon_sysfs_scheme_filters_ktype = { 643 .release = damon_sysfs_scheme_filters_release, 644 .sysfs_ops = &kobj_sysfs_ops, 645 .default_groups = damon_sysfs_scheme_filters_groups, 646 }; 647 648 /* 649 * watermarks directory 650 */ 651 652 struct damon_sysfs_watermarks { 653 struct kobject kobj; 654 enum damos_wmark_metric metric; 655 unsigned long interval_us; 656 unsigned long high; 657 unsigned long mid; 658 unsigned long low; 659 }; 660 661 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc( 662 enum damos_wmark_metric metric, unsigned long interval_us, 663 unsigned long high, unsigned long mid, unsigned long low) 664 { 665 struct damon_sysfs_watermarks *watermarks = kmalloc( 666 sizeof(*watermarks), GFP_KERNEL); 667 668 if (!watermarks) 669 return NULL; 670 watermarks->kobj = (struct kobject){}; 671 watermarks->metric = metric; 672 watermarks->interval_us = interval_us; 673 watermarks->high = high; 674 watermarks->mid = mid; 675 watermarks->low = low; 676 return watermarks; 677 } 678 679 /* Should match with enum damos_wmark_metric */ 680 static const char * const damon_sysfs_wmark_metric_strs[] = { 681 "none", 682 "free_mem_rate", 683 }; 684 685 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr, 686 char *buf) 687 { 688 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 689 struct damon_sysfs_watermarks, kobj); 690 691 return sysfs_emit(buf, "%s\n", 692 damon_sysfs_wmark_metric_strs[watermarks->metric]); 693 } 694 695 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr, 696 const char *buf, size_t count) 697 { 698 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 699 struct damon_sysfs_watermarks, kobj); 700 enum damos_wmark_metric metric; 701 702 for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) { 703 if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) { 704 watermarks->metric = metric; 705 return count; 706 } 707 } 708 return -EINVAL; 709 } 710 711 static ssize_t interval_us_show(struct kobject *kobj, 712 struct kobj_attribute *attr, char *buf) 713 { 714 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 715 struct damon_sysfs_watermarks, kobj); 716 717 return sysfs_emit(buf, "%lu\n", watermarks->interval_us); 718 } 719 720 static ssize_t interval_us_store(struct kobject *kobj, 721 struct kobj_attribute *attr, const char *buf, size_t count) 722 { 723 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 724 struct damon_sysfs_watermarks, kobj); 725 int err = kstrtoul(buf, 0, &watermarks->interval_us); 726 727 return err ? err : count; 728 } 729 730 static ssize_t high_show(struct kobject *kobj, 731 struct kobj_attribute *attr, char *buf) 732 { 733 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 734 struct damon_sysfs_watermarks, kobj); 735 736 return sysfs_emit(buf, "%lu\n", watermarks->high); 737 } 738 739 static ssize_t high_store(struct kobject *kobj, 740 struct kobj_attribute *attr, const char *buf, size_t count) 741 { 742 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 743 struct damon_sysfs_watermarks, kobj); 744 int err = kstrtoul(buf, 0, &watermarks->high); 745 746 return err ? err : count; 747 } 748 749 static ssize_t mid_show(struct kobject *kobj, 750 struct kobj_attribute *attr, char *buf) 751 { 752 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 753 struct damon_sysfs_watermarks, kobj); 754 755 return sysfs_emit(buf, "%lu\n", watermarks->mid); 756 } 757 758 static ssize_t mid_store(struct kobject *kobj, 759 struct kobj_attribute *attr, const char *buf, size_t count) 760 { 761 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 762 struct damon_sysfs_watermarks, kobj); 763 int err = kstrtoul(buf, 0, &watermarks->mid); 764 765 return err ? err : count; 766 } 767 768 static ssize_t low_show(struct kobject *kobj, 769 struct kobj_attribute *attr, char *buf) 770 { 771 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 772 struct damon_sysfs_watermarks, kobj); 773 774 return sysfs_emit(buf, "%lu\n", watermarks->low); 775 } 776 777 static ssize_t low_store(struct kobject *kobj, 778 struct kobj_attribute *attr, const char *buf, size_t count) 779 { 780 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 781 struct damon_sysfs_watermarks, kobj); 782 int err = kstrtoul(buf, 0, &watermarks->low); 783 784 return err ? err : count; 785 } 786 787 static void damon_sysfs_watermarks_release(struct kobject *kobj) 788 { 789 kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj)); 790 } 791 792 static struct kobj_attribute damon_sysfs_watermarks_metric_attr = 793 __ATTR_RW_MODE(metric, 0600); 794 795 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr = 796 __ATTR_RW_MODE(interval_us, 0600); 797 798 static struct kobj_attribute damon_sysfs_watermarks_high_attr = 799 __ATTR_RW_MODE(high, 0600); 800 801 static struct kobj_attribute damon_sysfs_watermarks_mid_attr = 802 __ATTR_RW_MODE(mid, 0600); 803 804 static struct kobj_attribute damon_sysfs_watermarks_low_attr = 805 __ATTR_RW_MODE(low, 0600); 806 807 static struct attribute *damon_sysfs_watermarks_attrs[] = { 808 &damon_sysfs_watermarks_metric_attr.attr, 809 &damon_sysfs_watermarks_interval_us_attr.attr, 810 &damon_sysfs_watermarks_high_attr.attr, 811 &damon_sysfs_watermarks_mid_attr.attr, 812 &damon_sysfs_watermarks_low_attr.attr, 813 NULL, 814 }; 815 ATTRIBUTE_GROUPS(damon_sysfs_watermarks); 816 817 static const struct kobj_type damon_sysfs_watermarks_ktype = { 818 .release = damon_sysfs_watermarks_release, 819 .sysfs_ops = &kobj_sysfs_ops, 820 .default_groups = damon_sysfs_watermarks_groups, 821 }; 822 823 /* 824 * quota goal directory 825 */ 826 827 struct damos_sysfs_quota_goal { 828 struct kobject kobj; 829 enum damos_quota_goal_metric metric; 830 unsigned long target_value; 831 unsigned long current_value; 832 }; 833 834 /* This should match with enum damos_action */ 835 static const char * const damos_sysfs_quota_goal_metric_strs[] = { 836 "user_input", 837 "some_mem_psi_us", 838 }; 839 840 static struct damos_sysfs_quota_goal *damos_sysfs_quota_goal_alloc(void) 841 { 842 return kzalloc(sizeof(struct damos_sysfs_quota_goal), GFP_KERNEL); 843 } 844 845 static ssize_t target_metric_show(struct kobject *kobj, 846 struct kobj_attribute *attr, char *buf) 847 { 848 struct damos_sysfs_quota_goal *goal = container_of(kobj, 849 struct damos_sysfs_quota_goal, kobj); 850 851 return sysfs_emit(buf, "%s\n", 852 damos_sysfs_quota_goal_metric_strs[goal->metric]); 853 } 854 855 static ssize_t target_metric_store(struct kobject *kobj, 856 struct kobj_attribute *attr, const char *buf, size_t count) 857 { 858 struct damos_sysfs_quota_goal *goal = container_of(kobj, 859 struct damos_sysfs_quota_goal, kobj); 860 enum damos_quota_goal_metric m; 861 862 for (m = 0; m < NR_DAMOS_QUOTA_GOAL_METRICS; m++) { 863 if (sysfs_streq(buf, damos_sysfs_quota_goal_metric_strs[m])) { 864 goal->metric = m; 865 return count; 866 } 867 } 868 return -EINVAL; 869 } 870 871 static ssize_t target_value_show(struct kobject *kobj, 872 struct kobj_attribute *attr, char *buf) 873 { 874 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 875 damos_sysfs_quota_goal, kobj); 876 877 return sysfs_emit(buf, "%lu\n", goal->target_value); 878 } 879 880 static ssize_t target_value_store(struct kobject *kobj, 881 struct kobj_attribute *attr, const char *buf, size_t count) 882 { 883 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 884 damos_sysfs_quota_goal, kobj); 885 int err = kstrtoul(buf, 0, &goal->target_value); 886 887 return err ? err : count; 888 } 889 890 static ssize_t current_value_show(struct kobject *kobj, 891 struct kobj_attribute *attr, char *buf) 892 { 893 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 894 damos_sysfs_quota_goal, kobj); 895 896 return sysfs_emit(buf, "%lu\n", goal->current_value); 897 } 898 899 static ssize_t current_value_store(struct kobject *kobj, 900 struct kobj_attribute *attr, const char *buf, size_t count) 901 { 902 struct damos_sysfs_quota_goal *goal = container_of(kobj, struct 903 damos_sysfs_quota_goal, kobj); 904 int err = kstrtoul(buf, 0, &goal->current_value); 905 906 /* feed callback should check existence of this file and read value */ 907 return err ? err : count; 908 } 909 910 static void damos_sysfs_quota_goal_release(struct kobject *kobj) 911 { 912 /* or, notify this release to the feed callback */ 913 kfree(container_of(kobj, struct damos_sysfs_quota_goal, kobj)); 914 } 915 916 static struct kobj_attribute damos_sysfs_quota_goal_target_metric_attr = 917 __ATTR_RW_MODE(target_metric, 0600); 918 919 static struct kobj_attribute damos_sysfs_quota_goal_target_value_attr = 920 __ATTR_RW_MODE(target_value, 0600); 921 922 static struct kobj_attribute damos_sysfs_quota_goal_current_value_attr = 923 __ATTR_RW_MODE(current_value, 0600); 924 925 static struct attribute *damos_sysfs_quota_goal_attrs[] = { 926 &damos_sysfs_quota_goal_target_metric_attr.attr, 927 &damos_sysfs_quota_goal_target_value_attr.attr, 928 &damos_sysfs_quota_goal_current_value_attr.attr, 929 NULL, 930 }; 931 ATTRIBUTE_GROUPS(damos_sysfs_quota_goal); 932 933 static const struct kobj_type damos_sysfs_quota_goal_ktype = { 934 .release = damos_sysfs_quota_goal_release, 935 .sysfs_ops = &kobj_sysfs_ops, 936 .default_groups = damos_sysfs_quota_goal_groups, 937 }; 938 939 /* 940 * quota goals directory 941 */ 942 943 struct damos_sysfs_quota_goals { 944 struct kobject kobj; 945 struct damos_sysfs_quota_goal **goals_arr; /* counted by nr */ 946 int nr; 947 }; 948 949 static struct damos_sysfs_quota_goals *damos_sysfs_quota_goals_alloc(void) 950 { 951 return kzalloc(sizeof(struct damos_sysfs_quota_goals), GFP_KERNEL); 952 } 953 954 static void damos_sysfs_quota_goals_rm_dirs( 955 struct damos_sysfs_quota_goals *goals) 956 { 957 struct damos_sysfs_quota_goal **goals_arr = goals->goals_arr; 958 int i; 959 960 for (i = 0; i < goals->nr; i++) 961 kobject_put(&goals_arr[i]->kobj); 962 goals->nr = 0; 963 kfree(goals_arr); 964 goals->goals_arr = NULL; 965 } 966 967 static int damos_sysfs_quota_goals_add_dirs( 968 struct damos_sysfs_quota_goals *goals, int nr_goals) 969 { 970 struct damos_sysfs_quota_goal **goals_arr, *goal; 971 int err, i; 972 973 damos_sysfs_quota_goals_rm_dirs(goals); 974 if (!nr_goals) 975 return 0; 976 977 goals_arr = kmalloc_array(nr_goals, sizeof(*goals_arr), 978 GFP_KERNEL | __GFP_NOWARN); 979 if (!goals_arr) 980 return -ENOMEM; 981 goals->goals_arr = goals_arr; 982 983 for (i = 0; i < nr_goals; i++) { 984 goal = damos_sysfs_quota_goal_alloc(); 985 if (!goal) { 986 damos_sysfs_quota_goals_rm_dirs(goals); 987 return -ENOMEM; 988 } 989 990 err = kobject_init_and_add(&goal->kobj, 991 &damos_sysfs_quota_goal_ktype, &goals->kobj, 992 "%d", i); 993 if (err) { 994 kobject_put(&goal->kobj); 995 damos_sysfs_quota_goals_rm_dirs(goals); 996 return err; 997 } 998 999 goals_arr[i] = goal; 1000 goals->nr++; 1001 } 1002 return 0; 1003 } 1004 1005 static ssize_t nr_goals_show(struct kobject *kobj, 1006 struct kobj_attribute *attr, char *buf) 1007 { 1008 struct damos_sysfs_quota_goals *goals = container_of(kobj, 1009 struct damos_sysfs_quota_goals, kobj); 1010 1011 return sysfs_emit(buf, "%d\n", goals->nr); 1012 } 1013 1014 static ssize_t nr_goals_store(struct kobject *kobj, 1015 struct kobj_attribute *attr, const char *buf, size_t count) 1016 { 1017 struct damos_sysfs_quota_goals *goals; 1018 int nr, err = kstrtoint(buf, 0, &nr); 1019 1020 if (err) 1021 return err; 1022 if (nr < 0) 1023 return -EINVAL; 1024 1025 goals = container_of(kobj, struct damos_sysfs_quota_goals, kobj); 1026 1027 if (!mutex_trylock(&damon_sysfs_lock)) 1028 return -EBUSY; 1029 err = damos_sysfs_quota_goals_add_dirs(goals, nr); 1030 mutex_unlock(&damon_sysfs_lock); 1031 if (err) 1032 return err; 1033 1034 return count; 1035 } 1036 1037 static void damos_sysfs_quota_goals_release(struct kobject *kobj) 1038 { 1039 kfree(container_of(kobj, struct damos_sysfs_quota_goals, kobj)); 1040 } 1041 1042 static struct kobj_attribute damos_sysfs_quota_goals_nr_attr = 1043 __ATTR_RW_MODE(nr_goals, 0600); 1044 1045 static struct attribute *damos_sysfs_quota_goals_attrs[] = { 1046 &damos_sysfs_quota_goals_nr_attr.attr, 1047 NULL, 1048 }; 1049 ATTRIBUTE_GROUPS(damos_sysfs_quota_goals); 1050 1051 static const struct kobj_type damos_sysfs_quota_goals_ktype = { 1052 .release = damos_sysfs_quota_goals_release, 1053 .sysfs_ops = &kobj_sysfs_ops, 1054 .default_groups = damos_sysfs_quota_goals_groups, 1055 }; 1056 1057 /* 1058 * scheme/weights directory 1059 */ 1060 1061 struct damon_sysfs_weights { 1062 struct kobject kobj; 1063 unsigned int sz; 1064 unsigned int nr_accesses; 1065 unsigned int age; 1066 }; 1067 1068 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz, 1069 unsigned int nr_accesses, unsigned int age) 1070 { 1071 struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights), 1072 GFP_KERNEL); 1073 1074 if (!weights) 1075 return NULL; 1076 weights->kobj = (struct kobject){}; 1077 weights->sz = sz; 1078 weights->nr_accesses = nr_accesses; 1079 weights->age = age; 1080 return weights; 1081 } 1082 1083 static ssize_t sz_permil_show(struct kobject *kobj, 1084 struct kobj_attribute *attr, char *buf) 1085 { 1086 struct damon_sysfs_weights *weights = container_of(kobj, 1087 struct damon_sysfs_weights, kobj); 1088 1089 return sysfs_emit(buf, "%u\n", weights->sz); 1090 } 1091 1092 static ssize_t sz_permil_store(struct kobject *kobj, 1093 struct kobj_attribute *attr, const char *buf, size_t count) 1094 { 1095 struct damon_sysfs_weights *weights = container_of(kobj, 1096 struct damon_sysfs_weights, kobj); 1097 int err = kstrtouint(buf, 0, &weights->sz); 1098 1099 return err ? err : count; 1100 } 1101 1102 static ssize_t nr_accesses_permil_show(struct kobject *kobj, 1103 struct kobj_attribute *attr, char *buf) 1104 { 1105 struct damon_sysfs_weights *weights = container_of(kobj, 1106 struct damon_sysfs_weights, kobj); 1107 1108 return sysfs_emit(buf, "%u\n", weights->nr_accesses); 1109 } 1110 1111 static ssize_t nr_accesses_permil_store(struct kobject *kobj, 1112 struct kobj_attribute *attr, const char *buf, size_t count) 1113 { 1114 struct damon_sysfs_weights *weights = container_of(kobj, 1115 struct damon_sysfs_weights, kobj); 1116 int err = kstrtouint(buf, 0, &weights->nr_accesses); 1117 1118 return err ? err : count; 1119 } 1120 1121 static ssize_t age_permil_show(struct kobject *kobj, 1122 struct kobj_attribute *attr, char *buf) 1123 { 1124 struct damon_sysfs_weights *weights = container_of(kobj, 1125 struct damon_sysfs_weights, kobj); 1126 1127 return sysfs_emit(buf, "%u\n", weights->age); 1128 } 1129 1130 static ssize_t age_permil_store(struct kobject *kobj, 1131 struct kobj_attribute *attr, const char *buf, size_t count) 1132 { 1133 struct damon_sysfs_weights *weights = container_of(kobj, 1134 struct damon_sysfs_weights, kobj); 1135 int err = kstrtouint(buf, 0, &weights->age); 1136 1137 return err ? err : count; 1138 } 1139 1140 static void damon_sysfs_weights_release(struct kobject *kobj) 1141 { 1142 kfree(container_of(kobj, struct damon_sysfs_weights, kobj)); 1143 } 1144 1145 static struct kobj_attribute damon_sysfs_weights_sz_attr = 1146 __ATTR_RW_MODE(sz_permil, 0600); 1147 1148 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr = 1149 __ATTR_RW_MODE(nr_accesses_permil, 0600); 1150 1151 static struct kobj_attribute damon_sysfs_weights_age_attr = 1152 __ATTR_RW_MODE(age_permil, 0600); 1153 1154 static struct attribute *damon_sysfs_weights_attrs[] = { 1155 &damon_sysfs_weights_sz_attr.attr, 1156 &damon_sysfs_weights_nr_accesses_attr.attr, 1157 &damon_sysfs_weights_age_attr.attr, 1158 NULL, 1159 }; 1160 ATTRIBUTE_GROUPS(damon_sysfs_weights); 1161 1162 static const struct kobj_type damon_sysfs_weights_ktype = { 1163 .release = damon_sysfs_weights_release, 1164 .sysfs_ops = &kobj_sysfs_ops, 1165 .default_groups = damon_sysfs_weights_groups, 1166 }; 1167 1168 /* 1169 * quotas directory 1170 */ 1171 1172 struct damon_sysfs_quotas { 1173 struct kobject kobj; 1174 struct damon_sysfs_weights *weights; 1175 struct damos_sysfs_quota_goals *goals; 1176 unsigned long ms; 1177 unsigned long sz; 1178 unsigned long reset_interval_ms; 1179 unsigned long effective_sz; /* Effective size quota in bytes */ 1180 }; 1181 1182 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void) 1183 { 1184 return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL); 1185 } 1186 1187 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas) 1188 { 1189 struct damon_sysfs_weights *weights; 1190 struct damos_sysfs_quota_goals *goals; 1191 int err; 1192 1193 weights = damon_sysfs_weights_alloc(0, 0, 0); 1194 if (!weights) 1195 return -ENOMEM; 1196 1197 err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype, 1198 "as->kobj, "weights"); 1199 if (err) { 1200 kobject_put(&weights->kobj); 1201 return err; 1202 } 1203 quotas->weights = weights; 1204 1205 goals = damos_sysfs_quota_goals_alloc(); 1206 if (!goals) { 1207 kobject_put(&weights->kobj); 1208 return -ENOMEM; 1209 } 1210 err = kobject_init_and_add(&goals->kobj, 1211 &damos_sysfs_quota_goals_ktype, "as->kobj, 1212 "goals"); 1213 if (err) { 1214 kobject_put(&weights->kobj); 1215 kobject_put(&goals->kobj); 1216 } else { 1217 quotas->goals = goals; 1218 } 1219 1220 return err; 1221 } 1222 1223 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas) 1224 { 1225 kobject_put("as->weights->kobj); 1226 damos_sysfs_quota_goals_rm_dirs(quotas->goals); 1227 kobject_put("as->goals->kobj); 1228 } 1229 1230 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr, 1231 char *buf) 1232 { 1233 struct damon_sysfs_quotas *quotas = container_of(kobj, 1234 struct damon_sysfs_quotas, kobj); 1235 1236 return sysfs_emit(buf, "%lu\n", quotas->ms); 1237 } 1238 1239 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr, 1240 const char *buf, size_t count) 1241 { 1242 struct damon_sysfs_quotas *quotas = container_of(kobj, 1243 struct damon_sysfs_quotas, kobj); 1244 int err = kstrtoul(buf, 0, "as->ms); 1245 1246 if (err) 1247 return -EINVAL; 1248 return count; 1249 } 1250 1251 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr, 1252 char *buf) 1253 { 1254 struct damon_sysfs_quotas *quotas = container_of(kobj, 1255 struct damon_sysfs_quotas, kobj); 1256 1257 return sysfs_emit(buf, "%lu\n", quotas->sz); 1258 } 1259 1260 static ssize_t bytes_store(struct kobject *kobj, 1261 struct kobj_attribute *attr, const char *buf, size_t count) 1262 { 1263 struct damon_sysfs_quotas *quotas = container_of(kobj, 1264 struct damon_sysfs_quotas, kobj); 1265 int err = kstrtoul(buf, 0, "as->sz); 1266 1267 if (err) 1268 return -EINVAL; 1269 return count; 1270 } 1271 1272 static ssize_t reset_interval_ms_show(struct kobject *kobj, 1273 struct kobj_attribute *attr, char *buf) 1274 { 1275 struct damon_sysfs_quotas *quotas = container_of(kobj, 1276 struct damon_sysfs_quotas, kobj); 1277 1278 return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms); 1279 } 1280 1281 static ssize_t reset_interval_ms_store(struct kobject *kobj, 1282 struct kobj_attribute *attr, const char *buf, size_t count) 1283 { 1284 struct damon_sysfs_quotas *quotas = container_of(kobj, 1285 struct damon_sysfs_quotas, kobj); 1286 int err = kstrtoul(buf, 0, "as->reset_interval_ms); 1287 1288 if (err) 1289 return -EINVAL; 1290 return count; 1291 } 1292 1293 static ssize_t effective_bytes_show(struct kobject *kobj, 1294 struct kobj_attribute *attr, char *buf) 1295 { 1296 struct damon_sysfs_quotas *quotas = container_of(kobj, 1297 struct damon_sysfs_quotas, kobj); 1298 1299 return sysfs_emit(buf, "%lu\n", quotas->effective_sz); 1300 } 1301 1302 static void damon_sysfs_quotas_release(struct kobject *kobj) 1303 { 1304 kfree(container_of(kobj, struct damon_sysfs_quotas, kobj)); 1305 } 1306 1307 static struct kobj_attribute damon_sysfs_quotas_ms_attr = 1308 __ATTR_RW_MODE(ms, 0600); 1309 1310 static struct kobj_attribute damon_sysfs_quotas_sz_attr = 1311 __ATTR_RW_MODE(bytes, 0600); 1312 1313 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr = 1314 __ATTR_RW_MODE(reset_interval_ms, 0600); 1315 1316 static struct kobj_attribute damon_sysfs_quotas_effective_bytes_attr = 1317 __ATTR_RO_MODE(effective_bytes, 0400); 1318 1319 static struct attribute *damon_sysfs_quotas_attrs[] = { 1320 &damon_sysfs_quotas_ms_attr.attr, 1321 &damon_sysfs_quotas_sz_attr.attr, 1322 &damon_sysfs_quotas_reset_interval_ms_attr.attr, 1323 &damon_sysfs_quotas_effective_bytes_attr.attr, 1324 NULL, 1325 }; 1326 ATTRIBUTE_GROUPS(damon_sysfs_quotas); 1327 1328 static const struct kobj_type damon_sysfs_quotas_ktype = { 1329 .release = damon_sysfs_quotas_release, 1330 .sysfs_ops = &kobj_sysfs_ops, 1331 .default_groups = damon_sysfs_quotas_groups, 1332 }; 1333 1334 /* 1335 * access_pattern directory 1336 */ 1337 1338 struct damon_sysfs_access_pattern { 1339 struct kobject kobj; 1340 struct damon_sysfs_ul_range *sz; 1341 struct damon_sysfs_ul_range *nr_accesses; 1342 struct damon_sysfs_ul_range *age; 1343 }; 1344 1345 static 1346 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void) 1347 { 1348 struct damon_sysfs_access_pattern *access_pattern = 1349 kmalloc(sizeof(*access_pattern), GFP_KERNEL); 1350 1351 if (!access_pattern) 1352 return NULL; 1353 access_pattern->kobj = (struct kobject){}; 1354 return access_pattern; 1355 } 1356 1357 static int damon_sysfs_access_pattern_add_range_dir( 1358 struct damon_sysfs_access_pattern *access_pattern, 1359 struct damon_sysfs_ul_range **range_dir_ptr, 1360 char *name) 1361 { 1362 struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0); 1363 int err; 1364 1365 if (!range) 1366 return -ENOMEM; 1367 err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype, 1368 &access_pattern->kobj, name); 1369 if (err) 1370 kobject_put(&range->kobj); 1371 else 1372 *range_dir_ptr = range; 1373 return err; 1374 } 1375 1376 static int damon_sysfs_access_pattern_add_dirs( 1377 struct damon_sysfs_access_pattern *access_pattern) 1378 { 1379 int err; 1380 1381 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1382 &access_pattern->sz, "sz"); 1383 if (err) 1384 goto put_sz_out; 1385 1386 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1387 &access_pattern->nr_accesses, "nr_accesses"); 1388 if (err) 1389 goto put_nr_accesses_sz_out; 1390 1391 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1392 &access_pattern->age, "age"); 1393 if (err) 1394 goto put_age_nr_accesses_sz_out; 1395 return 0; 1396 1397 put_age_nr_accesses_sz_out: 1398 kobject_put(&access_pattern->age->kobj); 1399 access_pattern->age = NULL; 1400 put_nr_accesses_sz_out: 1401 kobject_put(&access_pattern->nr_accesses->kobj); 1402 access_pattern->nr_accesses = NULL; 1403 put_sz_out: 1404 kobject_put(&access_pattern->sz->kobj); 1405 access_pattern->sz = NULL; 1406 return err; 1407 } 1408 1409 static void damon_sysfs_access_pattern_rm_dirs( 1410 struct damon_sysfs_access_pattern *access_pattern) 1411 { 1412 kobject_put(&access_pattern->sz->kobj); 1413 kobject_put(&access_pattern->nr_accesses->kobj); 1414 kobject_put(&access_pattern->age->kobj); 1415 } 1416 1417 static void damon_sysfs_access_pattern_release(struct kobject *kobj) 1418 { 1419 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj)); 1420 } 1421 1422 static struct attribute *damon_sysfs_access_pattern_attrs[] = { 1423 NULL, 1424 }; 1425 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern); 1426 1427 static const struct kobj_type damon_sysfs_access_pattern_ktype = { 1428 .release = damon_sysfs_access_pattern_release, 1429 .sysfs_ops = &kobj_sysfs_ops, 1430 .default_groups = damon_sysfs_access_pattern_groups, 1431 }; 1432 1433 /* 1434 * scheme directory 1435 */ 1436 1437 struct damon_sysfs_scheme { 1438 struct kobject kobj; 1439 enum damos_action action; 1440 struct damon_sysfs_access_pattern *access_pattern; 1441 unsigned long apply_interval_us; 1442 struct damon_sysfs_quotas *quotas; 1443 struct damon_sysfs_watermarks *watermarks; 1444 struct damon_sysfs_scheme_filters *filters; 1445 struct damon_sysfs_stats *stats; 1446 struct damon_sysfs_scheme_regions *tried_regions; 1447 }; 1448 1449 /* This should match with enum damos_action */ 1450 static const char * const damon_sysfs_damos_action_strs[] = { 1451 "willneed", 1452 "cold", 1453 "pageout", 1454 "hugepage", 1455 "nohugepage", 1456 "lru_prio", 1457 "lru_deprio", 1458 "stat", 1459 }; 1460 1461 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc( 1462 enum damos_action action, unsigned long apply_interval_us) 1463 { 1464 struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme), 1465 GFP_KERNEL); 1466 1467 if (!scheme) 1468 return NULL; 1469 scheme->kobj = (struct kobject){}; 1470 scheme->action = action; 1471 scheme->apply_interval_us = apply_interval_us; 1472 return scheme; 1473 } 1474 1475 static int damon_sysfs_scheme_set_access_pattern( 1476 struct damon_sysfs_scheme *scheme) 1477 { 1478 struct damon_sysfs_access_pattern *access_pattern; 1479 int err; 1480 1481 access_pattern = damon_sysfs_access_pattern_alloc(); 1482 if (!access_pattern) 1483 return -ENOMEM; 1484 err = kobject_init_and_add(&access_pattern->kobj, 1485 &damon_sysfs_access_pattern_ktype, &scheme->kobj, 1486 "access_pattern"); 1487 if (err) 1488 goto out; 1489 err = damon_sysfs_access_pattern_add_dirs(access_pattern); 1490 if (err) 1491 goto out; 1492 scheme->access_pattern = access_pattern; 1493 return 0; 1494 1495 out: 1496 kobject_put(&access_pattern->kobj); 1497 return err; 1498 } 1499 1500 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme) 1501 { 1502 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc(); 1503 int err; 1504 1505 if (!quotas) 1506 return -ENOMEM; 1507 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype, 1508 &scheme->kobj, "quotas"); 1509 if (err) 1510 goto out; 1511 err = damon_sysfs_quotas_add_dirs(quotas); 1512 if (err) 1513 goto out; 1514 scheme->quotas = quotas; 1515 return 0; 1516 1517 out: 1518 kobject_put("as->kobj); 1519 return err; 1520 } 1521 1522 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme) 1523 { 1524 struct damon_sysfs_watermarks *watermarks = 1525 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0); 1526 int err; 1527 1528 if (!watermarks) 1529 return -ENOMEM; 1530 err = kobject_init_and_add(&watermarks->kobj, 1531 &damon_sysfs_watermarks_ktype, &scheme->kobj, 1532 "watermarks"); 1533 if (err) 1534 kobject_put(&watermarks->kobj); 1535 else 1536 scheme->watermarks = watermarks; 1537 return err; 1538 } 1539 1540 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme) 1541 { 1542 struct damon_sysfs_scheme_filters *filters = 1543 damon_sysfs_scheme_filters_alloc(); 1544 int err; 1545 1546 if (!filters) 1547 return -ENOMEM; 1548 err = kobject_init_and_add(&filters->kobj, 1549 &damon_sysfs_scheme_filters_ktype, &scheme->kobj, 1550 "filters"); 1551 if (err) 1552 kobject_put(&filters->kobj); 1553 else 1554 scheme->filters = filters; 1555 return err; 1556 } 1557 1558 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme) 1559 { 1560 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc(); 1561 int err; 1562 1563 if (!stats) 1564 return -ENOMEM; 1565 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype, 1566 &scheme->kobj, "stats"); 1567 if (err) 1568 kobject_put(&stats->kobj); 1569 else 1570 scheme->stats = stats; 1571 return err; 1572 } 1573 1574 static int damon_sysfs_scheme_set_tried_regions( 1575 struct damon_sysfs_scheme *scheme) 1576 { 1577 struct damon_sysfs_scheme_regions *tried_regions = 1578 damon_sysfs_scheme_regions_alloc(); 1579 int err; 1580 1581 if (!tried_regions) 1582 return -ENOMEM; 1583 err = kobject_init_and_add(&tried_regions->kobj, 1584 &damon_sysfs_scheme_regions_ktype, &scheme->kobj, 1585 "tried_regions"); 1586 if (err) 1587 kobject_put(&tried_regions->kobj); 1588 else 1589 scheme->tried_regions = tried_regions; 1590 return err; 1591 } 1592 1593 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme) 1594 { 1595 int err; 1596 1597 err = damon_sysfs_scheme_set_access_pattern(scheme); 1598 if (err) 1599 return err; 1600 err = damon_sysfs_scheme_set_quotas(scheme); 1601 if (err) 1602 goto put_access_pattern_out; 1603 err = damon_sysfs_scheme_set_watermarks(scheme); 1604 if (err) 1605 goto put_quotas_access_pattern_out; 1606 err = damon_sysfs_scheme_set_filters(scheme); 1607 if (err) 1608 goto put_watermarks_quotas_access_pattern_out; 1609 err = damon_sysfs_scheme_set_stats(scheme); 1610 if (err) 1611 goto put_filters_watermarks_quotas_access_pattern_out; 1612 err = damon_sysfs_scheme_set_tried_regions(scheme); 1613 if (err) 1614 goto put_tried_regions_out; 1615 return 0; 1616 1617 put_tried_regions_out: 1618 kobject_put(&scheme->tried_regions->kobj); 1619 scheme->tried_regions = NULL; 1620 put_filters_watermarks_quotas_access_pattern_out: 1621 kobject_put(&scheme->filters->kobj); 1622 scheme->filters = NULL; 1623 put_watermarks_quotas_access_pattern_out: 1624 kobject_put(&scheme->watermarks->kobj); 1625 scheme->watermarks = NULL; 1626 put_quotas_access_pattern_out: 1627 kobject_put(&scheme->quotas->kobj); 1628 scheme->quotas = NULL; 1629 put_access_pattern_out: 1630 kobject_put(&scheme->access_pattern->kobj); 1631 scheme->access_pattern = NULL; 1632 return err; 1633 } 1634 1635 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme) 1636 { 1637 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 1638 kobject_put(&scheme->access_pattern->kobj); 1639 damon_sysfs_quotas_rm_dirs(scheme->quotas); 1640 kobject_put(&scheme->quotas->kobj); 1641 kobject_put(&scheme->watermarks->kobj); 1642 damon_sysfs_scheme_filters_rm_dirs(scheme->filters); 1643 kobject_put(&scheme->filters->kobj); 1644 kobject_put(&scheme->stats->kobj); 1645 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions); 1646 kobject_put(&scheme->tried_regions->kobj); 1647 } 1648 1649 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr, 1650 char *buf) 1651 { 1652 struct damon_sysfs_scheme *scheme = container_of(kobj, 1653 struct damon_sysfs_scheme, kobj); 1654 1655 return sysfs_emit(buf, "%s\n", 1656 damon_sysfs_damos_action_strs[scheme->action]); 1657 } 1658 1659 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr, 1660 const char *buf, size_t count) 1661 { 1662 struct damon_sysfs_scheme *scheme = container_of(kobj, 1663 struct damon_sysfs_scheme, kobj); 1664 enum damos_action action; 1665 1666 for (action = 0; action < NR_DAMOS_ACTIONS; action++) { 1667 if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) { 1668 scheme->action = action; 1669 return count; 1670 } 1671 } 1672 return -EINVAL; 1673 } 1674 1675 static ssize_t apply_interval_us_show(struct kobject *kobj, 1676 struct kobj_attribute *attr, char *buf) 1677 { 1678 struct damon_sysfs_scheme *scheme = container_of(kobj, 1679 struct damon_sysfs_scheme, kobj); 1680 1681 return sysfs_emit(buf, "%lu\n", scheme->apply_interval_us); 1682 } 1683 1684 static ssize_t apply_interval_us_store(struct kobject *kobj, 1685 struct kobj_attribute *attr, const char *buf, size_t count) 1686 { 1687 struct damon_sysfs_scheme *scheme = container_of(kobj, 1688 struct damon_sysfs_scheme, kobj); 1689 int err = kstrtoul(buf, 0, &scheme->apply_interval_us); 1690 1691 return err ? err : count; 1692 } 1693 1694 static void damon_sysfs_scheme_release(struct kobject *kobj) 1695 { 1696 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj)); 1697 } 1698 1699 static struct kobj_attribute damon_sysfs_scheme_action_attr = 1700 __ATTR_RW_MODE(action, 0600); 1701 1702 static struct kobj_attribute damon_sysfs_scheme_apply_interval_us_attr = 1703 __ATTR_RW_MODE(apply_interval_us, 0600); 1704 1705 static struct attribute *damon_sysfs_scheme_attrs[] = { 1706 &damon_sysfs_scheme_action_attr.attr, 1707 &damon_sysfs_scheme_apply_interval_us_attr.attr, 1708 NULL, 1709 }; 1710 ATTRIBUTE_GROUPS(damon_sysfs_scheme); 1711 1712 static const struct kobj_type damon_sysfs_scheme_ktype = { 1713 .release = damon_sysfs_scheme_release, 1714 .sysfs_ops = &kobj_sysfs_ops, 1715 .default_groups = damon_sysfs_scheme_groups, 1716 }; 1717 1718 /* 1719 * schemes directory 1720 */ 1721 1722 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void) 1723 { 1724 return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL); 1725 } 1726 1727 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes) 1728 { 1729 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr; 1730 int i; 1731 1732 for (i = 0; i < schemes->nr; i++) { 1733 damon_sysfs_scheme_rm_dirs(schemes_arr[i]); 1734 kobject_put(&schemes_arr[i]->kobj); 1735 } 1736 schemes->nr = 0; 1737 kfree(schemes_arr); 1738 schemes->schemes_arr = NULL; 1739 } 1740 1741 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes, 1742 int nr_schemes) 1743 { 1744 struct damon_sysfs_scheme **schemes_arr, *scheme; 1745 int err, i; 1746 1747 damon_sysfs_schemes_rm_dirs(schemes); 1748 if (!nr_schemes) 1749 return 0; 1750 1751 schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr), 1752 GFP_KERNEL | __GFP_NOWARN); 1753 if (!schemes_arr) 1754 return -ENOMEM; 1755 schemes->schemes_arr = schemes_arr; 1756 1757 for (i = 0; i < nr_schemes; i++) { 1758 /* 1759 * apply_interval_us as 0 means same to aggregation interval 1760 * (same to before-apply_interval behavior) 1761 */ 1762 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT, 0); 1763 if (!scheme) { 1764 damon_sysfs_schemes_rm_dirs(schemes); 1765 return -ENOMEM; 1766 } 1767 1768 err = kobject_init_and_add(&scheme->kobj, 1769 &damon_sysfs_scheme_ktype, &schemes->kobj, 1770 "%d", i); 1771 if (err) 1772 goto out; 1773 err = damon_sysfs_scheme_add_dirs(scheme); 1774 if (err) 1775 goto out; 1776 1777 schemes_arr[i] = scheme; 1778 schemes->nr++; 1779 } 1780 return 0; 1781 1782 out: 1783 damon_sysfs_schemes_rm_dirs(schemes); 1784 kobject_put(&scheme->kobj); 1785 return err; 1786 } 1787 1788 static ssize_t nr_schemes_show(struct kobject *kobj, 1789 struct kobj_attribute *attr, char *buf) 1790 { 1791 struct damon_sysfs_schemes *schemes = container_of(kobj, 1792 struct damon_sysfs_schemes, kobj); 1793 1794 return sysfs_emit(buf, "%d\n", schemes->nr); 1795 } 1796 1797 static ssize_t nr_schemes_store(struct kobject *kobj, 1798 struct kobj_attribute *attr, const char *buf, size_t count) 1799 { 1800 struct damon_sysfs_schemes *schemes; 1801 int nr, err = kstrtoint(buf, 0, &nr); 1802 1803 if (err) 1804 return err; 1805 if (nr < 0) 1806 return -EINVAL; 1807 1808 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj); 1809 1810 if (!mutex_trylock(&damon_sysfs_lock)) 1811 return -EBUSY; 1812 err = damon_sysfs_schemes_add_dirs(schemes, nr); 1813 mutex_unlock(&damon_sysfs_lock); 1814 if (err) 1815 return err; 1816 return count; 1817 } 1818 1819 static void damon_sysfs_schemes_release(struct kobject *kobj) 1820 { 1821 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj)); 1822 } 1823 1824 static struct kobj_attribute damon_sysfs_schemes_nr_attr = 1825 __ATTR_RW_MODE(nr_schemes, 0600); 1826 1827 static struct attribute *damon_sysfs_schemes_attrs[] = { 1828 &damon_sysfs_schemes_nr_attr.attr, 1829 NULL, 1830 }; 1831 ATTRIBUTE_GROUPS(damon_sysfs_schemes); 1832 1833 const struct kobj_type damon_sysfs_schemes_ktype = { 1834 .release = damon_sysfs_schemes_release, 1835 .sysfs_ops = &kobj_sysfs_ops, 1836 .default_groups = damon_sysfs_schemes_groups, 1837 }; 1838 1839 static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg, 1840 char *memcg_path_buf, char *path) 1841 { 1842 #ifdef CONFIG_MEMCG 1843 cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX); 1844 if (sysfs_streq(memcg_path_buf, path)) 1845 return true; 1846 #endif /* CONFIG_MEMCG */ 1847 return false; 1848 } 1849 1850 static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id) 1851 { 1852 struct mem_cgroup *memcg; 1853 char *path; 1854 bool found = false; 1855 1856 if (!memcg_path) 1857 return -EINVAL; 1858 1859 path = kmalloc(sizeof(*path) * PATH_MAX, GFP_KERNEL); 1860 if (!path) 1861 return -ENOMEM; 1862 1863 for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg; 1864 memcg = mem_cgroup_iter(NULL, memcg, NULL)) { 1865 /* skip removed memcg */ 1866 if (!mem_cgroup_id(memcg)) 1867 continue; 1868 if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) { 1869 *id = mem_cgroup_id(memcg); 1870 found = true; 1871 break; 1872 } 1873 } 1874 1875 kfree(path); 1876 return found ? 0 : -EINVAL; 1877 } 1878 1879 static int damon_sysfs_set_scheme_filters(struct damos *scheme, 1880 struct damon_sysfs_scheme_filters *sysfs_filters) 1881 { 1882 int i; 1883 struct damos_filter *filter, *next; 1884 1885 damos_for_each_filter_safe(filter, next, scheme) 1886 damos_destroy_filter(filter); 1887 1888 for (i = 0; i < sysfs_filters->nr; i++) { 1889 struct damon_sysfs_scheme_filter *sysfs_filter = 1890 sysfs_filters->filters_arr[i]; 1891 struct damos_filter *filter = 1892 damos_new_filter(sysfs_filter->type, 1893 sysfs_filter->matching); 1894 int err; 1895 1896 if (!filter) 1897 return -ENOMEM; 1898 if (filter->type == DAMOS_FILTER_TYPE_MEMCG) { 1899 err = damon_sysfs_memcg_path_to_id( 1900 sysfs_filter->memcg_path, 1901 &filter->memcg_id); 1902 if (err) { 1903 damos_destroy_filter(filter); 1904 return err; 1905 } 1906 } else if (filter->type == DAMOS_FILTER_TYPE_ADDR) { 1907 if (sysfs_filter->addr_range.end < 1908 sysfs_filter->addr_range.start) { 1909 damos_destroy_filter(filter); 1910 return -EINVAL; 1911 } 1912 filter->addr_range = sysfs_filter->addr_range; 1913 } else if (filter->type == DAMOS_FILTER_TYPE_TARGET) { 1914 filter->target_idx = sysfs_filter->target_idx; 1915 } 1916 1917 damos_add_filter(scheme, filter); 1918 } 1919 return 0; 1920 } 1921 1922 static int damos_sysfs_set_quota_score( 1923 struct damos_sysfs_quota_goals *sysfs_goals, 1924 struct damos_quota *quota) 1925 { 1926 struct damos_quota_goal *goal, *next; 1927 int i; 1928 1929 damos_for_each_quota_goal_safe(goal, next, quota) 1930 damos_destroy_quota_goal(goal); 1931 1932 for (i = 0; i < sysfs_goals->nr; i++) { 1933 struct damos_sysfs_quota_goal *sysfs_goal = 1934 sysfs_goals->goals_arr[i]; 1935 1936 if (!sysfs_goal->target_value) 1937 continue; 1938 1939 goal = damos_new_quota_goal(sysfs_goal->metric, 1940 sysfs_goal->target_value); 1941 if (!goal) 1942 return -ENOMEM; 1943 if (sysfs_goal->metric == DAMOS_QUOTA_USER_INPUT) 1944 goal->current_value = sysfs_goal->current_value; 1945 damos_add_quota_goal(quota, goal); 1946 } 1947 return 0; 1948 } 1949 1950 int damos_sysfs_set_quota_scores(struct damon_sysfs_schemes *sysfs_schemes, 1951 struct damon_ctx *ctx) 1952 { 1953 struct damos *scheme; 1954 int i = 0; 1955 1956 damon_for_each_scheme(scheme, ctx) { 1957 struct damon_sysfs_scheme *sysfs_scheme; 1958 int err; 1959 1960 /* user could have removed the scheme sysfs dir */ 1961 if (i >= sysfs_schemes->nr) 1962 break; 1963 1964 sysfs_scheme = sysfs_schemes->schemes_arr[i]; 1965 err = damos_sysfs_set_quota_score(sysfs_scheme->quotas->goals, 1966 &scheme->quota); 1967 if (err) 1968 /* kdamond will clean up schemes and terminated */ 1969 return err; 1970 i++; 1971 } 1972 return 0; 1973 } 1974 1975 void damos_sysfs_update_effective_quotas( 1976 struct damon_sysfs_schemes *sysfs_schemes, 1977 struct damon_ctx *ctx) 1978 { 1979 struct damos *scheme; 1980 int schemes_idx = 0; 1981 1982 damon_for_each_scheme(scheme, ctx) { 1983 struct damon_sysfs_quotas *sysfs_quotas; 1984 1985 /* user could have removed the scheme sysfs dir */ 1986 if (schemes_idx >= sysfs_schemes->nr) 1987 break; 1988 1989 sysfs_quotas = 1990 sysfs_schemes->schemes_arr[schemes_idx++]->quotas; 1991 sysfs_quotas->effective_sz = scheme->quota.esz; 1992 } 1993 } 1994 1995 static struct damos *damon_sysfs_mk_scheme( 1996 struct damon_sysfs_scheme *sysfs_scheme) 1997 { 1998 struct damon_sysfs_access_pattern *access_pattern = 1999 sysfs_scheme->access_pattern; 2000 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; 2001 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; 2002 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; 2003 struct damon_sysfs_scheme_filters *sysfs_filters = 2004 sysfs_scheme->filters; 2005 struct damos *scheme; 2006 int err; 2007 2008 struct damos_access_pattern pattern = { 2009 .min_sz_region = access_pattern->sz->min, 2010 .max_sz_region = access_pattern->sz->max, 2011 .min_nr_accesses = access_pattern->nr_accesses->min, 2012 .max_nr_accesses = access_pattern->nr_accesses->max, 2013 .min_age_region = access_pattern->age->min, 2014 .max_age_region = access_pattern->age->max, 2015 }; 2016 struct damos_quota quota = { 2017 .ms = sysfs_quotas->ms, 2018 .sz = sysfs_quotas->sz, 2019 .reset_interval = sysfs_quotas->reset_interval_ms, 2020 .weight_sz = sysfs_weights->sz, 2021 .weight_nr_accesses = sysfs_weights->nr_accesses, 2022 .weight_age = sysfs_weights->age, 2023 }; 2024 struct damos_watermarks wmarks = { 2025 .metric = sysfs_wmarks->metric, 2026 .interval = sysfs_wmarks->interval_us, 2027 .high = sysfs_wmarks->high, 2028 .mid = sysfs_wmarks->mid, 2029 .low = sysfs_wmarks->low, 2030 }; 2031 2032 scheme = damon_new_scheme(&pattern, sysfs_scheme->action, 2033 sysfs_scheme->apply_interval_us, "a, &wmarks); 2034 if (!scheme) 2035 return NULL; 2036 2037 err = damos_sysfs_set_quota_score(sysfs_quotas->goals, &scheme->quota); 2038 if (err) { 2039 damon_destroy_scheme(scheme); 2040 return NULL; 2041 } 2042 2043 err = damon_sysfs_set_scheme_filters(scheme, sysfs_filters); 2044 if (err) { 2045 damon_destroy_scheme(scheme); 2046 return NULL; 2047 } 2048 return scheme; 2049 } 2050 2051 static void damon_sysfs_update_scheme(struct damos *scheme, 2052 struct damon_sysfs_scheme *sysfs_scheme) 2053 { 2054 struct damon_sysfs_access_pattern *access_pattern = 2055 sysfs_scheme->access_pattern; 2056 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; 2057 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; 2058 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; 2059 int err; 2060 2061 scheme->pattern.min_sz_region = access_pattern->sz->min; 2062 scheme->pattern.max_sz_region = access_pattern->sz->max; 2063 scheme->pattern.min_nr_accesses = access_pattern->nr_accesses->min; 2064 scheme->pattern.max_nr_accesses = access_pattern->nr_accesses->max; 2065 scheme->pattern.min_age_region = access_pattern->age->min; 2066 scheme->pattern.max_age_region = access_pattern->age->max; 2067 2068 scheme->action = sysfs_scheme->action; 2069 scheme->apply_interval_us = sysfs_scheme->apply_interval_us; 2070 2071 scheme->quota.ms = sysfs_quotas->ms; 2072 scheme->quota.sz = sysfs_quotas->sz; 2073 scheme->quota.reset_interval = sysfs_quotas->reset_interval_ms; 2074 scheme->quota.weight_sz = sysfs_weights->sz; 2075 scheme->quota.weight_nr_accesses = sysfs_weights->nr_accesses; 2076 scheme->quota.weight_age = sysfs_weights->age; 2077 2078 err = damos_sysfs_set_quota_score(sysfs_quotas->goals, &scheme->quota); 2079 if (err) { 2080 damon_destroy_scheme(scheme); 2081 return; 2082 } 2083 2084 scheme->wmarks.metric = sysfs_wmarks->metric; 2085 scheme->wmarks.interval = sysfs_wmarks->interval_us; 2086 scheme->wmarks.high = sysfs_wmarks->high; 2087 scheme->wmarks.mid = sysfs_wmarks->mid; 2088 scheme->wmarks.low = sysfs_wmarks->low; 2089 2090 err = damon_sysfs_set_scheme_filters(scheme, sysfs_scheme->filters); 2091 if (err) 2092 damon_destroy_scheme(scheme); 2093 } 2094 2095 int damon_sysfs_set_schemes(struct damon_ctx *ctx, 2096 struct damon_sysfs_schemes *sysfs_schemes) 2097 { 2098 struct damos *scheme, *next; 2099 int i = 0; 2100 2101 damon_for_each_scheme_safe(scheme, next, ctx) { 2102 if (i < sysfs_schemes->nr) 2103 damon_sysfs_update_scheme(scheme, 2104 sysfs_schemes->schemes_arr[i]); 2105 else 2106 damon_destroy_scheme(scheme); 2107 i++; 2108 } 2109 2110 for (; i < sysfs_schemes->nr; i++) { 2111 struct damos *scheme, *next; 2112 2113 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]); 2114 if (!scheme) { 2115 damon_for_each_scheme_safe(scheme, next, ctx) 2116 damon_destroy_scheme(scheme); 2117 return -ENOMEM; 2118 } 2119 damon_add_scheme(ctx, scheme); 2120 } 2121 return 0; 2122 } 2123 2124 void damon_sysfs_schemes_update_stats( 2125 struct damon_sysfs_schemes *sysfs_schemes, 2126 struct damon_ctx *ctx) 2127 { 2128 struct damos *scheme; 2129 int schemes_idx = 0; 2130 2131 damon_for_each_scheme(scheme, ctx) { 2132 struct damon_sysfs_stats *sysfs_stats; 2133 2134 /* user could have removed the scheme sysfs dir */ 2135 if (schemes_idx >= sysfs_schemes->nr) 2136 break; 2137 2138 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats; 2139 sysfs_stats->nr_tried = scheme->stat.nr_tried; 2140 sysfs_stats->sz_tried = scheme->stat.sz_tried; 2141 sysfs_stats->nr_applied = scheme->stat.nr_applied; 2142 sysfs_stats->sz_applied = scheme->stat.sz_applied; 2143 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds; 2144 } 2145 } 2146 2147 /* 2148 * damon_sysfs_schemes that need to update its schemes regions dir. Protected 2149 * by damon_sysfs_lock 2150 */ 2151 static struct damon_sysfs_schemes *damon_sysfs_schemes_for_damos_callback; 2152 static int damon_sysfs_schemes_region_idx; 2153 static bool damos_regions_upd_total_bytes_only; 2154 2155 /* 2156 * DAMON callback that called before damos apply. While this callback is 2157 * registered, damon_sysfs_lock should be held to ensure the regions 2158 * directories exist. 2159 */ 2160 static int damon_sysfs_before_damos_apply(struct damon_ctx *ctx, 2161 struct damon_target *t, struct damon_region *r, 2162 struct damos *s) 2163 { 2164 struct damos *scheme; 2165 struct damon_sysfs_scheme_regions *sysfs_regions; 2166 struct damon_sysfs_scheme_region *region; 2167 struct damon_sysfs_schemes *sysfs_schemes = 2168 damon_sysfs_schemes_for_damos_callback; 2169 int schemes_idx = 0; 2170 2171 damon_for_each_scheme(scheme, ctx) { 2172 if (scheme == s) 2173 break; 2174 schemes_idx++; 2175 } 2176 2177 /* user could have removed the scheme sysfs dir */ 2178 if (schemes_idx >= sysfs_schemes->nr) 2179 return 0; 2180 2181 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions; 2182 if (sysfs_regions->upd_status == DAMOS_TRIED_REGIONS_UPD_FINISHED) 2183 return 0; 2184 if (sysfs_regions->upd_status == DAMOS_TRIED_REGIONS_UPD_IDLE) 2185 sysfs_regions->upd_status = DAMOS_TRIED_REGIONS_UPD_STARTED; 2186 sysfs_regions->total_bytes += r->ar.end - r->ar.start; 2187 if (damos_regions_upd_total_bytes_only) 2188 return 0; 2189 2190 region = damon_sysfs_scheme_region_alloc(r); 2191 if (!region) 2192 return 0; 2193 list_add_tail(®ion->list, &sysfs_regions->regions_list); 2194 sysfs_regions->nr_regions++; 2195 if (kobject_init_and_add(®ion->kobj, 2196 &damon_sysfs_scheme_region_ktype, 2197 &sysfs_regions->kobj, "%d", 2198 damon_sysfs_schemes_region_idx++)) { 2199 kobject_put(®ion->kobj); 2200 } 2201 return 0; 2202 } 2203 2204 /* 2205 * DAMON callback that called after each accesses sampling. While this 2206 * callback is registered, damon_sysfs_lock should be held to ensure the 2207 * regions directories exist. 2208 */ 2209 void damos_sysfs_mark_finished_regions_updates(struct damon_ctx *ctx) 2210 { 2211 struct damon_sysfs_schemes *sysfs_schemes = 2212 damon_sysfs_schemes_for_damos_callback; 2213 struct damon_sysfs_scheme_regions *sysfs_regions; 2214 int i; 2215 2216 for (i = 0; i < sysfs_schemes->nr; i++) { 2217 sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions; 2218 if (sysfs_regions->upd_status == 2219 DAMOS_TRIED_REGIONS_UPD_STARTED || 2220 time_after(jiffies, 2221 sysfs_regions->upd_timeout_jiffies)) 2222 sysfs_regions->upd_status = 2223 DAMOS_TRIED_REGIONS_UPD_FINISHED; 2224 } 2225 } 2226 2227 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */ 2228 int damon_sysfs_schemes_clear_regions( 2229 struct damon_sysfs_schemes *sysfs_schemes, 2230 struct damon_ctx *ctx) 2231 { 2232 struct damos *scheme; 2233 int schemes_idx = 0; 2234 2235 damon_for_each_scheme(scheme, ctx) { 2236 struct damon_sysfs_scheme *sysfs_scheme; 2237 2238 /* user could have removed the scheme sysfs dir */ 2239 if (schemes_idx >= sysfs_schemes->nr) 2240 break; 2241 2242 sysfs_scheme = sysfs_schemes->schemes_arr[schemes_idx++]; 2243 damon_sysfs_scheme_regions_rm_dirs( 2244 sysfs_scheme->tried_regions); 2245 sysfs_scheme->tried_regions->total_bytes = 0; 2246 } 2247 return 0; 2248 } 2249 2250 static struct damos *damos_sysfs_nth_scheme(int n, struct damon_ctx *ctx) 2251 { 2252 struct damos *scheme; 2253 int i = 0; 2254 2255 damon_for_each_scheme(scheme, ctx) { 2256 if (i == n) 2257 return scheme; 2258 i++; 2259 } 2260 return NULL; 2261 } 2262 2263 static void damos_tried_regions_init_upd_status( 2264 struct damon_sysfs_schemes *sysfs_schemes, 2265 struct damon_ctx *ctx) 2266 { 2267 int i; 2268 struct damos *scheme; 2269 struct damon_sysfs_scheme_regions *sysfs_regions; 2270 2271 for (i = 0; i < sysfs_schemes->nr; i++) { 2272 sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions; 2273 scheme = damos_sysfs_nth_scheme(i, ctx); 2274 if (!scheme) { 2275 sysfs_regions->upd_status = 2276 DAMOS_TRIED_REGIONS_UPD_FINISHED; 2277 continue; 2278 } 2279 sysfs_regions->upd_status = DAMOS_TRIED_REGIONS_UPD_IDLE; 2280 sysfs_regions->upd_timeout_jiffies = jiffies + 2281 2 * usecs_to_jiffies(scheme->apply_interval_us ? 2282 scheme->apply_interval_us : 2283 ctx->attrs.aggr_interval); 2284 } 2285 } 2286 2287 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */ 2288 int damon_sysfs_schemes_update_regions_start( 2289 struct damon_sysfs_schemes *sysfs_schemes, 2290 struct damon_ctx *ctx, bool total_bytes_only) 2291 { 2292 damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx); 2293 damon_sysfs_schemes_for_damos_callback = sysfs_schemes; 2294 damos_tried_regions_init_upd_status(sysfs_schemes, ctx); 2295 damos_regions_upd_total_bytes_only = total_bytes_only; 2296 ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply; 2297 return 0; 2298 } 2299 2300 bool damos_sysfs_regions_upd_done(void) 2301 { 2302 struct damon_sysfs_schemes *sysfs_schemes = 2303 damon_sysfs_schemes_for_damos_callback; 2304 struct damon_sysfs_scheme_regions *sysfs_regions; 2305 int i; 2306 2307 for (i = 0; i < sysfs_schemes->nr; i++) { 2308 sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions; 2309 if (sysfs_regions->upd_status != 2310 DAMOS_TRIED_REGIONS_UPD_FINISHED) 2311 return false; 2312 } 2313 return true; 2314 } 2315 2316 /* 2317 * Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock. Caller 2318 * should unlock damon_sysfs_lock which held before 2319 * damon_sysfs_schemes_update_regions_start() 2320 */ 2321 int damon_sysfs_schemes_update_regions_stop(struct damon_ctx *ctx) 2322 { 2323 damon_sysfs_schemes_for_damos_callback = NULL; 2324 ctx->callback.before_damos_apply = NULL; 2325 damon_sysfs_schemes_region_idx = 0; 2326 return 0; 2327 } 2328