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() and 131 * ->after_sampling() callbacks. 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() callback (damon_sysfs_after_sampling()) after the call 136 * is called only after the scheme is completely applied 137 * to the given snapshot. Hence the callback knows the situation by showing 138 * 'started' status, and sets the status as 'finished'. Then, 139 * damon_sysfs_before_damos_apply() understands the situation by showing the 140 * 'finished' status and do nothing. 141 * 142 * Finally, the tried regions request handling finisher function 143 * (damon_sysfs_schemes_update_regions_stop()) unregisters the callbacks. 144 */ 145 enum damos_sysfs_regions_upd_status { 146 DAMOS_TRIED_REGIONS_UPD_IDLE, 147 DAMOS_TRIED_REGIONS_UPD_STARTED, 148 DAMOS_TRIED_REGIONS_UPD_FINISHED, 149 }; 150 151 struct damon_sysfs_scheme_regions { 152 struct kobject kobj; 153 struct list_head regions_list; 154 int nr_regions; 155 unsigned long total_bytes; 156 enum damos_sysfs_regions_upd_status upd_status; 157 }; 158 159 static struct damon_sysfs_scheme_regions * 160 damon_sysfs_scheme_regions_alloc(void) 161 { 162 struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions), 163 GFP_KERNEL); 164 165 regions->kobj = (struct kobject){}; 166 INIT_LIST_HEAD(®ions->regions_list); 167 regions->nr_regions = 0; 168 regions->total_bytes = 0; 169 regions->upd_status = DAMOS_TRIED_REGIONS_UPD_IDLE; 170 return regions; 171 } 172 173 static ssize_t total_bytes_show(struct kobject *kobj, 174 struct kobj_attribute *attr, char *buf) 175 { 176 struct damon_sysfs_scheme_regions *regions = container_of(kobj, 177 struct damon_sysfs_scheme_regions, kobj); 178 179 return sysfs_emit(buf, "%lu\n", regions->total_bytes); 180 } 181 182 static void damon_sysfs_scheme_regions_rm_dirs( 183 struct damon_sysfs_scheme_regions *regions) 184 { 185 struct damon_sysfs_scheme_region *r, *next; 186 187 list_for_each_entry_safe(r, next, ®ions->regions_list, list) { 188 /* release function deletes it from the list */ 189 kobject_put(&r->kobj); 190 regions->nr_regions--; 191 } 192 } 193 194 static void damon_sysfs_scheme_regions_release(struct kobject *kobj) 195 { 196 kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj)); 197 } 198 199 static struct kobj_attribute damon_sysfs_scheme_regions_total_bytes_attr = 200 __ATTR_RO_MODE(total_bytes, 0400); 201 202 static struct attribute *damon_sysfs_scheme_regions_attrs[] = { 203 &damon_sysfs_scheme_regions_total_bytes_attr.attr, 204 NULL, 205 }; 206 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions); 207 208 static const struct kobj_type damon_sysfs_scheme_regions_ktype = { 209 .release = damon_sysfs_scheme_regions_release, 210 .sysfs_ops = &kobj_sysfs_ops, 211 .default_groups = damon_sysfs_scheme_regions_groups, 212 }; 213 214 /* 215 * schemes/stats directory 216 */ 217 218 struct damon_sysfs_stats { 219 struct kobject kobj; 220 unsigned long nr_tried; 221 unsigned long sz_tried; 222 unsigned long nr_applied; 223 unsigned long sz_applied; 224 unsigned long qt_exceeds; 225 }; 226 227 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void) 228 { 229 return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL); 230 } 231 232 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr, 233 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_tried); 239 } 240 241 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr, 242 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_tried); 248 } 249 250 static ssize_t nr_applied_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->nr_applied); 257 } 258 259 static ssize_t sz_applied_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->sz_applied); 266 } 267 268 static ssize_t qt_exceeds_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->qt_exceeds); 275 } 276 277 static void damon_sysfs_stats_release(struct kobject *kobj) 278 { 279 kfree(container_of(kobj, struct damon_sysfs_stats, kobj)); 280 } 281 282 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr = 283 __ATTR_RO_MODE(nr_tried, 0400); 284 285 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr = 286 __ATTR_RO_MODE(sz_tried, 0400); 287 288 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr = 289 __ATTR_RO_MODE(nr_applied, 0400); 290 291 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr = 292 __ATTR_RO_MODE(sz_applied, 0400); 293 294 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr = 295 __ATTR_RO_MODE(qt_exceeds, 0400); 296 297 static struct attribute *damon_sysfs_stats_attrs[] = { 298 &damon_sysfs_stats_nr_tried_attr.attr, 299 &damon_sysfs_stats_sz_tried_attr.attr, 300 &damon_sysfs_stats_nr_applied_attr.attr, 301 &damon_sysfs_stats_sz_applied_attr.attr, 302 &damon_sysfs_stats_qt_exceeds_attr.attr, 303 NULL, 304 }; 305 ATTRIBUTE_GROUPS(damon_sysfs_stats); 306 307 static const struct kobj_type damon_sysfs_stats_ktype = { 308 .release = damon_sysfs_stats_release, 309 .sysfs_ops = &kobj_sysfs_ops, 310 .default_groups = damon_sysfs_stats_groups, 311 }; 312 313 /* 314 * filter directory 315 */ 316 317 struct damon_sysfs_scheme_filter { 318 struct kobject kobj; 319 enum damos_filter_type type; 320 bool matching; 321 char *memcg_path; 322 struct damon_addr_range addr_range; 323 int target_idx; 324 }; 325 326 static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc(void) 327 { 328 return kzalloc(sizeof(struct damon_sysfs_scheme_filter), GFP_KERNEL); 329 } 330 331 /* Should match with enum damos_filter_type */ 332 static const char * const damon_sysfs_scheme_filter_type_strs[] = { 333 "anon", 334 "memcg", 335 "addr", 336 "target", 337 }; 338 339 static ssize_t type_show(struct kobject *kobj, 340 struct kobj_attribute *attr, char *buf) 341 { 342 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 343 struct damon_sysfs_scheme_filter, kobj); 344 345 return sysfs_emit(buf, "%s\n", 346 damon_sysfs_scheme_filter_type_strs[filter->type]); 347 } 348 349 static ssize_t type_store(struct kobject *kobj, 350 struct kobj_attribute *attr, const char *buf, size_t count) 351 { 352 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 353 struct damon_sysfs_scheme_filter, kobj); 354 enum damos_filter_type type; 355 ssize_t ret = -EINVAL; 356 357 for (type = 0; type < NR_DAMOS_FILTER_TYPES; type++) { 358 if (sysfs_streq(buf, damon_sysfs_scheme_filter_type_strs[ 359 type])) { 360 filter->type = type; 361 ret = count; 362 break; 363 } 364 } 365 return ret; 366 } 367 368 static ssize_t matching_show(struct kobject *kobj, 369 struct kobj_attribute *attr, char *buf) 370 { 371 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 372 struct damon_sysfs_scheme_filter, kobj); 373 374 return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N'); 375 } 376 377 static ssize_t matching_store(struct kobject *kobj, 378 struct kobj_attribute *attr, const char *buf, size_t count) 379 { 380 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 381 struct damon_sysfs_scheme_filter, kobj); 382 bool matching; 383 int err = kstrtobool(buf, &matching); 384 385 if (err) 386 return err; 387 388 filter->matching = matching; 389 return count; 390 } 391 392 static ssize_t memcg_path_show(struct kobject *kobj, 393 struct kobj_attribute *attr, char *buf) 394 { 395 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 396 struct damon_sysfs_scheme_filter, kobj); 397 398 return sysfs_emit(buf, "%s\n", 399 filter->memcg_path ? filter->memcg_path : ""); 400 } 401 402 static ssize_t memcg_path_store(struct kobject *kobj, 403 struct kobj_attribute *attr, const char *buf, size_t count) 404 { 405 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 406 struct damon_sysfs_scheme_filter, kobj); 407 char *path = kmalloc(sizeof(*path) * (count + 1), GFP_KERNEL); 408 409 if (!path) 410 return -ENOMEM; 411 412 strscpy(path, buf, count + 1); 413 filter->memcg_path = path; 414 return count; 415 } 416 417 static ssize_t addr_start_show(struct kobject *kobj, 418 struct kobj_attribute *attr, char *buf) 419 { 420 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 421 struct damon_sysfs_scheme_filter, kobj); 422 423 return sysfs_emit(buf, "%lu\n", filter->addr_range.start); 424 } 425 426 static ssize_t addr_start_store(struct kobject *kobj, 427 struct kobj_attribute *attr, const char *buf, size_t count) 428 { 429 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 430 struct damon_sysfs_scheme_filter, kobj); 431 int err = kstrtoul(buf, 0, &filter->addr_range.start); 432 433 return err ? err : count; 434 } 435 436 static ssize_t addr_end_show(struct kobject *kobj, 437 struct kobj_attribute *attr, char *buf) 438 { 439 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 440 struct damon_sysfs_scheme_filter, kobj); 441 442 return sysfs_emit(buf, "%lu\n", filter->addr_range.end); 443 } 444 445 static ssize_t addr_end_store(struct kobject *kobj, 446 struct kobj_attribute *attr, const char *buf, size_t count) 447 { 448 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 449 struct damon_sysfs_scheme_filter, kobj); 450 int err = kstrtoul(buf, 0, &filter->addr_range.end); 451 452 return err ? err : count; 453 } 454 455 static ssize_t damon_target_idx_show(struct kobject *kobj, 456 struct kobj_attribute *attr, char *buf) 457 { 458 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 459 struct damon_sysfs_scheme_filter, kobj); 460 461 return sysfs_emit(buf, "%d\n", filter->target_idx); 462 } 463 464 static ssize_t damon_target_idx_store(struct kobject *kobj, 465 struct kobj_attribute *attr, const char *buf, size_t count) 466 { 467 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 468 struct damon_sysfs_scheme_filter, kobj); 469 int err = kstrtoint(buf, 0, &filter->target_idx); 470 471 return err ? err : count; 472 } 473 474 static void damon_sysfs_scheme_filter_release(struct kobject *kobj) 475 { 476 struct damon_sysfs_scheme_filter *filter = container_of(kobj, 477 struct damon_sysfs_scheme_filter, kobj); 478 479 kfree(filter->memcg_path); 480 kfree(filter); 481 } 482 483 static struct kobj_attribute damon_sysfs_scheme_filter_type_attr = 484 __ATTR_RW_MODE(type, 0600); 485 486 static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr = 487 __ATTR_RW_MODE(matching, 0600); 488 489 static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr = 490 __ATTR_RW_MODE(memcg_path, 0600); 491 492 static struct kobj_attribute damon_sysfs_scheme_filter_addr_start_attr = 493 __ATTR_RW_MODE(addr_start, 0600); 494 495 static struct kobj_attribute damon_sysfs_scheme_filter_addr_end_attr = 496 __ATTR_RW_MODE(addr_end, 0600); 497 498 static struct kobj_attribute damon_sysfs_scheme_filter_damon_target_idx_attr = 499 __ATTR_RW_MODE(damon_target_idx, 0600); 500 501 static struct attribute *damon_sysfs_scheme_filter_attrs[] = { 502 &damon_sysfs_scheme_filter_type_attr.attr, 503 &damon_sysfs_scheme_filter_matching_attr.attr, 504 &damon_sysfs_scheme_filter_memcg_path_attr.attr, 505 &damon_sysfs_scheme_filter_addr_start_attr.attr, 506 &damon_sysfs_scheme_filter_addr_end_attr.attr, 507 &damon_sysfs_scheme_filter_damon_target_idx_attr.attr, 508 NULL, 509 }; 510 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter); 511 512 static const struct kobj_type damon_sysfs_scheme_filter_ktype = { 513 .release = damon_sysfs_scheme_filter_release, 514 .sysfs_ops = &kobj_sysfs_ops, 515 .default_groups = damon_sysfs_scheme_filter_groups, 516 }; 517 518 /* 519 * filters directory 520 */ 521 522 struct damon_sysfs_scheme_filters { 523 struct kobject kobj; 524 struct damon_sysfs_scheme_filter **filters_arr; 525 int nr; 526 }; 527 528 static struct damon_sysfs_scheme_filters * 529 damon_sysfs_scheme_filters_alloc(void) 530 { 531 return kzalloc(sizeof(struct damon_sysfs_scheme_filters), GFP_KERNEL); 532 } 533 534 static void damon_sysfs_scheme_filters_rm_dirs( 535 struct damon_sysfs_scheme_filters *filters) 536 { 537 struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr; 538 int i; 539 540 for (i = 0; i < filters->nr; i++) 541 kobject_put(&filters_arr[i]->kobj); 542 filters->nr = 0; 543 kfree(filters_arr); 544 filters->filters_arr = NULL; 545 } 546 547 static int damon_sysfs_scheme_filters_add_dirs( 548 struct damon_sysfs_scheme_filters *filters, int nr_filters) 549 { 550 struct damon_sysfs_scheme_filter **filters_arr, *filter; 551 int err, i; 552 553 damon_sysfs_scheme_filters_rm_dirs(filters); 554 if (!nr_filters) 555 return 0; 556 557 filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr), 558 GFP_KERNEL | __GFP_NOWARN); 559 if (!filters_arr) 560 return -ENOMEM; 561 filters->filters_arr = filters_arr; 562 563 for (i = 0; i < nr_filters; i++) { 564 filter = damon_sysfs_scheme_filter_alloc(); 565 if (!filter) { 566 damon_sysfs_scheme_filters_rm_dirs(filters); 567 return -ENOMEM; 568 } 569 570 err = kobject_init_and_add(&filter->kobj, 571 &damon_sysfs_scheme_filter_ktype, 572 &filters->kobj, "%d", i); 573 if (err) { 574 kobject_put(&filter->kobj); 575 damon_sysfs_scheme_filters_rm_dirs(filters); 576 return err; 577 } 578 579 filters_arr[i] = filter; 580 filters->nr++; 581 } 582 return 0; 583 } 584 585 static ssize_t nr_filters_show(struct kobject *kobj, 586 struct kobj_attribute *attr, char *buf) 587 { 588 struct damon_sysfs_scheme_filters *filters = container_of(kobj, 589 struct damon_sysfs_scheme_filters, kobj); 590 591 return sysfs_emit(buf, "%d\n", filters->nr); 592 } 593 594 static ssize_t nr_filters_store(struct kobject *kobj, 595 struct kobj_attribute *attr, const char *buf, size_t count) 596 { 597 struct damon_sysfs_scheme_filters *filters; 598 int nr, err = kstrtoint(buf, 0, &nr); 599 600 if (err) 601 return err; 602 if (nr < 0) 603 return -EINVAL; 604 605 filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj); 606 607 if (!mutex_trylock(&damon_sysfs_lock)) 608 return -EBUSY; 609 err = damon_sysfs_scheme_filters_add_dirs(filters, nr); 610 mutex_unlock(&damon_sysfs_lock); 611 if (err) 612 return err; 613 614 return count; 615 } 616 617 static void damon_sysfs_scheme_filters_release(struct kobject *kobj) 618 { 619 kfree(container_of(kobj, struct damon_sysfs_scheme_filters, kobj)); 620 } 621 622 static struct kobj_attribute damon_sysfs_scheme_filters_nr_attr = 623 __ATTR_RW_MODE(nr_filters, 0600); 624 625 static struct attribute *damon_sysfs_scheme_filters_attrs[] = { 626 &damon_sysfs_scheme_filters_nr_attr.attr, 627 NULL, 628 }; 629 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filters); 630 631 static const struct kobj_type damon_sysfs_scheme_filters_ktype = { 632 .release = damon_sysfs_scheme_filters_release, 633 .sysfs_ops = &kobj_sysfs_ops, 634 .default_groups = damon_sysfs_scheme_filters_groups, 635 }; 636 637 /* 638 * watermarks directory 639 */ 640 641 struct damon_sysfs_watermarks { 642 struct kobject kobj; 643 enum damos_wmark_metric metric; 644 unsigned long interval_us; 645 unsigned long high; 646 unsigned long mid; 647 unsigned long low; 648 }; 649 650 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc( 651 enum damos_wmark_metric metric, unsigned long interval_us, 652 unsigned long high, unsigned long mid, unsigned long low) 653 { 654 struct damon_sysfs_watermarks *watermarks = kmalloc( 655 sizeof(*watermarks), GFP_KERNEL); 656 657 if (!watermarks) 658 return NULL; 659 watermarks->kobj = (struct kobject){}; 660 watermarks->metric = metric; 661 watermarks->interval_us = interval_us; 662 watermarks->high = high; 663 watermarks->mid = mid; 664 watermarks->low = low; 665 return watermarks; 666 } 667 668 /* Should match with enum damos_wmark_metric */ 669 static const char * const damon_sysfs_wmark_metric_strs[] = { 670 "none", 671 "free_mem_rate", 672 }; 673 674 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr, 675 char *buf) 676 { 677 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 678 struct damon_sysfs_watermarks, kobj); 679 680 return sysfs_emit(buf, "%s\n", 681 damon_sysfs_wmark_metric_strs[watermarks->metric]); 682 } 683 684 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr, 685 const char *buf, size_t count) 686 { 687 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 688 struct damon_sysfs_watermarks, kobj); 689 enum damos_wmark_metric metric; 690 691 for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) { 692 if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) { 693 watermarks->metric = metric; 694 return count; 695 } 696 } 697 return -EINVAL; 698 } 699 700 static ssize_t interval_us_show(struct kobject *kobj, 701 struct kobj_attribute *attr, char *buf) 702 { 703 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 704 struct damon_sysfs_watermarks, kobj); 705 706 return sysfs_emit(buf, "%lu\n", watermarks->interval_us); 707 } 708 709 static ssize_t interval_us_store(struct kobject *kobj, 710 struct kobj_attribute *attr, const char *buf, size_t count) 711 { 712 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 713 struct damon_sysfs_watermarks, kobj); 714 int err = kstrtoul(buf, 0, &watermarks->interval_us); 715 716 return err ? err : count; 717 } 718 719 static ssize_t high_show(struct kobject *kobj, 720 struct kobj_attribute *attr, char *buf) 721 { 722 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 723 struct damon_sysfs_watermarks, kobj); 724 725 return sysfs_emit(buf, "%lu\n", watermarks->high); 726 } 727 728 static ssize_t high_store(struct kobject *kobj, 729 struct kobj_attribute *attr, const char *buf, size_t count) 730 { 731 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 732 struct damon_sysfs_watermarks, kobj); 733 int err = kstrtoul(buf, 0, &watermarks->high); 734 735 return err ? err : count; 736 } 737 738 static ssize_t mid_show(struct kobject *kobj, 739 struct kobj_attribute *attr, char *buf) 740 { 741 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 742 struct damon_sysfs_watermarks, kobj); 743 744 return sysfs_emit(buf, "%lu\n", watermarks->mid); 745 } 746 747 static ssize_t mid_store(struct kobject *kobj, 748 struct kobj_attribute *attr, const char *buf, size_t count) 749 { 750 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 751 struct damon_sysfs_watermarks, kobj); 752 int err = kstrtoul(buf, 0, &watermarks->mid); 753 754 return err ? err : count; 755 } 756 757 static ssize_t low_show(struct kobject *kobj, 758 struct kobj_attribute *attr, char *buf) 759 { 760 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 761 struct damon_sysfs_watermarks, kobj); 762 763 return sysfs_emit(buf, "%lu\n", watermarks->low); 764 } 765 766 static ssize_t low_store(struct kobject *kobj, 767 struct kobj_attribute *attr, const char *buf, size_t count) 768 { 769 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 770 struct damon_sysfs_watermarks, kobj); 771 int err = kstrtoul(buf, 0, &watermarks->low); 772 773 return err ? err : count; 774 } 775 776 static void damon_sysfs_watermarks_release(struct kobject *kobj) 777 { 778 kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj)); 779 } 780 781 static struct kobj_attribute damon_sysfs_watermarks_metric_attr = 782 __ATTR_RW_MODE(metric, 0600); 783 784 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr = 785 __ATTR_RW_MODE(interval_us, 0600); 786 787 static struct kobj_attribute damon_sysfs_watermarks_high_attr = 788 __ATTR_RW_MODE(high, 0600); 789 790 static struct kobj_attribute damon_sysfs_watermarks_mid_attr = 791 __ATTR_RW_MODE(mid, 0600); 792 793 static struct kobj_attribute damon_sysfs_watermarks_low_attr = 794 __ATTR_RW_MODE(low, 0600); 795 796 static struct attribute *damon_sysfs_watermarks_attrs[] = { 797 &damon_sysfs_watermarks_metric_attr.attr, 798 &damon_sysfs_watermarks_interval_us_attr.attr, 799 &damon_sysfs_watermarks_high_attr.attr, 800 &damon_sysfs_watermarks_mid_attr.attr, 801 &damon_sysfs_watermarks_low_attr.attr, 802 NULL, 803 }; 804 ATTRIBUTE_GROUPS(damon_sysfs_watermarks); 805 806 static const struct kobj_type damon_sysfs_watermarks_ktype = { 807 .release = damon_sysfs_watermarks_release, 808 .sysfs_ops = &kobj_sysfs_ops, 809 .default_groups = damon_sysfs_watermarks_groups, 810 }; 811 812 /* 813 * scheme/weights directory 814 */ 815 816 struct damon_sysfs_weights { 817 struct kobject kobj; 818 unsigned int sz; 819 unsigned int nr_accesses; 820 unsigned int age; 821 }; 822 823 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz, 824 unsigned int nr_accesses, unsigned int age) 825 { 826 struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights), 827 GFP_KERNEL); 828 829 if (!weights) 830 return NULL; 831 weights->kobj = (struct kobject){}; 832 weights->sz = sz; 833 weights->nr_accesses = nr_accesses; 834 weights->age = age; 835 return weights; 836 } 837 838 static ssize_t sz_permil_show(struct kobject *kobj, 839 struct kobj_attribute *attr, char *buf) 840 { 841 struct damon_sysfs_weights *weights = container_of(kobj, 842 struct damon_sysfs_weights, kobj); 843 844 return sysfs_emit(buf, "%u\n", weights->sz); 845 } 846 847 static ssize_t sz_permil_store(struct kobject *kobj, 848 struct kobj_attribute *attr, const char *buf, size_t count) 849 { 850 struct damon_sysfs_weights *weights = container_of(kobj, 851 struct damon_sysfs_weights, kobj); 852 int err = kstrtouint(buf, 0, &weights->sz); 853 854 return err ? err : count; 855 } 856 857 static ssize_t nr_accesses_permil_show(struct kobject *kobj, 858 struct kobj_attribute *attr, char *buf) 859 { 860 struct damon_sysfs_weights *weights = container_of(kobj, 861 struct damon_sysfs_weights, kobj); 862 863 return sysfs_emit(buf, "%u\n", weights->nr_accesses); 864 } 865 866 static ssize_t nr_accesses_permil_store(struct kobject *kobj, 867 struct kobj_attribute *attr, const char *buf, size_t count) 868 { 869 struct damon_sysfs_weights *weights = container_of(kobj, 870 struct damon_sysfs_weights, kobj); 871 int err = kstrtouint(buf, 0, &weights->nr_accesses); 872 873 return err ? err : count; 874 } 875 876 static ssize_t age_permil_show(struct kobject *kobj, 877 struct kobj_attribute *attr, char *buf) 878 { 879 struct damon_sysfs_weights *weights = container_of(kobj, 880 struct damon_sysfs_weights, kobj); 881 882 return sysfs_emit(buf, "%u\n", weights->age); 883 } 884 885 static ssize_t age_permil_store(struct kobject *kobj, 886 struct kobj_attribute *attr, const char *buf, size_t count) 887 { 888 struct damon_sysfs_weights *weights = container_of(kobj, 889 struct damon_sysfs_weights, kobj); 890 int err = kstrtouint(buf, 0, &weights->age); 891 892 return err ? err : count; 893 } 894 895 static void damon_sysfs_weights_release(struct kobject *kobj) 896 { 897 kfree(container_of(kobj, struct damon_sysfs_weights, kobj)); 898 } 899 900 static struct kobj_attribute damon_sysfs_weights_sz_attr = 901 __ATTR_RW_MODE(sz_permil, 0600); 902 903 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr = 904 __ATTR_RW_MODE(nr_accesses_permil, 0600); 905 906 static struct kobj_attribute damon_sysfs_weights_age_attr = 907 __ATTR_RW_MODE(age_permil, 0600); 908 909 static struct attribute *damon_sysfs_weights_attrs[] = { 910 &damon_sysfs_weights_sz_attr.attr, 911 &damon_sysfs_weights_nr_accesses_attr.attr, 912 &damon_sysfs_weights_age_attr.attr, 913 NULL, 914 }; 915 ATTRIBUTE_GROUPS(damon_sysfs_weights); 916 917 static const struct kobj_type damon_sysfs_weights_ktype = { 918 .release = damon_sysfs_weights_release, 919 .sysfs_ops = &kobj_sysfs_ops, 920 .default_groups = damon_sysfs_weights_groups, 921 }; 922 923 /* 924 * quotas directory 925 */ 926 927 struct damon_sysfs_quotas { 928 struct kobject kobj; 929 struct damon_sysfs_weights *weights; 930 unsigned long ms; 931 unsigned long sz; 932 unsigned long reset_interval_ms; 933 }; 934 935 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void) 936 { 937 return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL); 938 } 939 940 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas) 941 { 942 struct damon_sysfs_weights *weights; 943 int err; 944 945 weights = damon_sysfs_weights_alloc(0, 0, 0); 946 if (!weights) 947 return -ENOMEM; 948 949 err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype, 950 "as->kobj, "weights"); 951 if (err) 952 kobject_put(&weights->kobj); 953 else 954 quotas->weights = weights; 955 return err; 956 } 957 958 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas) 959 { 960 kobject_put("as->weights->kobj); 961 } 962 963 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr, 964 char *buf) 965 { 966 struct damon_sysfs_quotas *quotas = container_of(kobj, 967 struct damon_sysfs_quotas, kobj); 968 969 return sysfs_emit(buf, "%lu\n", quotas->ms); 970 } 971 972 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr, 973 const char *buf, size_t count) 974 { 975 struct damon_sysfs_quotas *quotas = container_of(kobj, 976 struct damon_sysfs_quotas, kobj); 977 int err = kstrtoul(buf, 0, "as->ms); 978 979 if (err) 980 return -EINVAL; 981 return count; 982 } 983 984 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr, 985 char *buf) 986 { 987 struct damon_sysfs_quotas *quotas = container_of(kobj, 988 struct damon_sysfs_quotas, kobj); 989 990 return sysfs_emit(buf, "%lu\n", quotas->sz); 991 } 992 993 static ssize_t bytes_store(struct kobject *kobj, 994 struct kobj_attribute *attr, const char *buf, size_t count) 995 { 996 struct damon_sysfs_quotas *quotas = container_of(kobj, 997 struct damon_sysfs_quotas, kobj); 998 int err = kstrtoul(buf, 0, "as->sz); 999 1000 if (err) 1001 return -EINVAL; 1002 return count; 1003 } 1004 1005 static ssize_t reset_interval_ms_show(struct kobject *kobj, 1006 struct kobj_attribute *attr, char *buf) 1007 { 1008 struct damon_sysfs_quotas *quotas = container_of(kobj, 1009 struct damon_sysfs_quotas, kobj); 1010 1011 return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms); 1012 } 1013 1014 static ssize_t reset_interval_ms_store(struct kobject *kobj, 1015 struct kobj_attribute *attr, const char *buf, size_t count) 1016 { 1017 struct damon_sysfs_quotas *quotas = container_of(kobj, 1018 struct damon_sysfs_quotas, kobj); 1019 int err = kstrtoul(buf, 0, "as->reset_interval_ms); 1020 1021 if (err) 1022 return -EINVAL; 1023 return count; 1024 } 1025 1026 static void damon_sysfs_quotas_release(struct kobject *kobj) 1027 { 1028 kfree(container_of(kobj, struct damon_sysfs_quotas, kobj)); 1029 } 1030 1031 static struct kobj_attribute damon_sysfs_quotas_ms_attr = 1032 __ATTR_RW_MODE(ms, 0600); 1033 1034 static struct kobj_attribute damon_sysfs_quotas_sz_attr = 1035 __ATTR_RW_MODE(bytes, 0600); 1036 1037 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr = 1038 __ATTR_RW_MODE(reset_interval_ms, 0600); 1039 1040 static struct attribute *damon_sysfs_quotas_attrs[] = { 1041 &damon_sysfs_quotas_ms_attr.attr, 1042 &damon_sysfs_quotas_sz_attr.attr, 1043 &damon_sysfs_quotas_reset_interval_ms_attr.attr, 1044 NULL, 1045 }; 1046 ATTRIBUTE_GROUPS(damon_sysfs_quotas); 1047 1048 static const struct kobj_type damon_sysfs_quotas_ktype = { 1049 .release = damon_sysfs_quotas_release, 1050 .sysfs_ops = &kobj_sysfs_ops, 1051 .default_groups = damon_sysfs_quotas_groups, 1052 }; 1053 1054 /* 1055 * access_pattern directory 1056 */ 1057 1058 struct damon_sysfs_access_pattern { 1059 struct kobject kobj; 1060 struct damon_sysfs_ul_range *sz; 1061 struct damon_sysfs_ul_range *nr_accesses; 1062 struct damon_sysfs_ul_range *age; 1063 }; 1064 1065 static 1066 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void) 1067 { 1068 struct damon_sysfs_access_pattern *access_pattern = 1069 kmalloc(sizeof(*access_pattern), GFP_KERNEL); 1070 1071 if (!access_pattern) 1072 return NULL; 1073 access_pattern->kobj = (struct kobject){}; 1074 return access_pattern; 1075 } 1076 1077 static int damon_sysfs_access_pattern_add_range_dir( 1078 struct damon_sysfs_access_pattern *access_pattern, 1079 struct damon_sysfs_ul_range **range_dir_ptr, 1080 char *name) 1081 { 1082 struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0); 1083 int err; 1084 1085 if (!range) 1086 return -ENOMEM; 1087 err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype, 1088 &access_pattern->kobj, name); 1089 if (err) 1090 kobject_put(&range->kobj); 1091 else 1092 *range_dir_ptr = range; 1093 return err; 1094 } 1095 1096 static int damon_sysfs_access_pattern_add_dirs( 1097 struct damon_sysfs_access_pattern *access_pattern) 1098 { 1099 int err; 1100 1101 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1102 &access_pattern->sz, "sz"); 1103 if (err) 1104 goto put_sz_out; 1105 1106 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1107 &access_pattern->nr_accesses, "nr_accesses"); 1108 if (err) 1109 goto put_nr_accesses_sz_out; 1110 1111 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 1112 &access_pattern->age, "age"); 1113 if (err) 1114 goto put_age_nr_accesses_sz_out; 1115 return 0; 1116 1117 put_age_nr_accesses_sz_out: 1118 kobject_put(&access_pattern->age->kobj); 1119 access_pattern->age = NULL; 1120 put_nr_accesses_sz_out: 1121 kobject_put(&access_pattern->nr_accesses->kobj); 1122 access_pattern->nr_accesses = NULL; 1123 put_sz_out: 1124 kobject_put(&access_pattern->sz->kobj); 1125 access_pattern->sz = NULL; 1126 return err; 1127 } 1128 1129 static void damon_sysfs_access_pattern_rm_dirs( 1130 struct damon_sysfs_access_pattern *access_pattern) 1131 { 1132 kobject_put(&access_pattern->sz->kobj); 1133 kobject_put(&access_pattern->nr_accesses->kobj); 1134 kobject_put(&access_pattern->age->kobj); 1135 } 1136 1137 static void damon_sysfs_access_pattern_release(struct kobject *kobj) 1138 { 1139 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj)); 1140 } 1141 1142 static struct attribute *damon_sysfs_access_pattern_attrs[] = { 1143 NULL, 1144 }; 1145 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern); 1146 1147 static const struct kobj_type damon_sysfs_access_pattern_ktype = { 1148 .release = damon_sysfs_access_pattern_release, 1149 .sysfs_ops = &kobj_sysfs_ops, 1150 .default_groups = damon_sysfs_access_pattern_groups, 1151 }; 1152 1153 /* 1154 * scheme directory 1155 */ 1156 1157 struct damon_sysfs_scheme { 1158 struct kobject kobj; 1159 enum damos_action action; 1160 struct damon_sysfs_access_pattern *access_pattern; 1161 unsigned long apply_interval_us; 1162 struct damon_sysfs_quotas *quotas; 1163 struct damon_sysfs_watermarks *watermarks; 1164 struct damon_sysfs_scheme_filters *filters; 1165 struct damon_sysfs_stats *stats; 1166 struct damon_sysfs_scheme_regions *tried_regions; 1167 }; 1168 1169 /* This should match with enum damos_action */ 1170 static const char * const damon_sysfs_damos_action_strs[] = { 1171 "willneed", 1172 "cold", 1173 "pageout", 1174 "hugepage", 1175 "nohugepage", 1176 "lru_prio", 1177 "lru_deprio", 1178 "stat", 1179 }; 1180 1181 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc( 1182 enum damos_action action, unsigned long apply_interval_us) 1183 { 1184 struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme), 1185 GFP_KERNEL); 1186 1187 if (!scheme) 1188 return NULL; 1189 scheme->kobj = (struct kobject){}; 1190 scheme->action = action; 1191 scheme->apply_interval_us = apply_interval_us; 1192 return scheme; 1193 } 1194 1195 static int damon_sysfs_scheme_set_access_pattern( 1196 struct damon_sysfs_scheme *scheme) 1197 { 1198 struct damon_sysfs_access_pattern *access_pattern; 1199 int err; 1200 1201 access_pattern = damon_sysfs_access_pattern_alloc(); 1202 if (!access_pattern) 1203 return -ENOMEM; 1204 err = kobject_init_and_add(&access_pattern->kobj, 1205 &damon_sysfs_access_pattern_ktype, &scheme->kobj, 1206 "access_pattern"); 1207 if (err) 1208 goto out; 1209 err = damon_sysfs_access_pattern_add_dirs(access_pattern); 1210 if (err) 1211 goto out; 1212 scheme->access_pattern = access_pattern; 1213 return 0; 1214 1215 out: 1216 kobject_put(&access_pattern->kobj); 1217 return err; 1218 } 1219 1220 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme) 1221 { 1222 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc(); 1223 int err; 1224 1225 if (!quotas) 1226 return -ENOMEM; 1227 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype, 1228 &scheme->kobj, "quotas"); 1229 if (err) 1230 goto out; 1231 err = damon_sysfs_quotas_add_dirs(quotas); 1232 if (err) 1233 goto out; 1234 scheme->quotas = quotas; 1235 return 0; 1236 1237 out: 1238 kobject_put("as->kobj); 1239 return err; 1240 } 1241 1242 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme) 1243 { 1244 struct damon_sysfs_watermarks *watermarks = 1245 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0); 1246 int err; 1247 1248 if (!watermarks) 1249 return -ENOMEM; 1250 err = kobject_init_and_add(&watermarks->kobj, 1251 &damon_sysfs_watermarks_ktype, &scheme->kobj, 1252 "watermarks"); 1253 if (err) 1254 kobject_put(&watermarks->kobj); 1255 else 1256 scheme->watermarks = watermarks; 1257 return err; 1258 } 1259 1260 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme) 1261 { 1262 struct damon_sysfs_scheme_filters *filters = 1263 damon_sysfs_scheme_filters_alloc(); 1264 int err; 1265 1266 if (!filters) 1267 return -ENOMEM; 1268 err = kobject_init_and_add(&filters->kobj, 1269 &damon_sysfs_scheme_filters_ktype, &scheme->kobj, 1270 "filters"); 1271 if (err) 1272 kobject_put(&filters->kobj); 1273 else 1274 scheme->filters = filters; 1275 return err; 1276 } 1277 1278 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme) 1279 { 1280 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc(); 1281 int err; 1282 1283 if (!stats) 1284 return -ENOMEM; 1285 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype, 1286 &scheme->kobj, "stats"); 1287 if (err) 1288 kobject_put(&stats->kobj); 1289 else 1290 scheme->stats = stats; 1291 return err; 1292 } 1293 1294 static int damon_sysfs_scheme_set_tried_regions( 1295 struct damon_sysfs_scheme *scheme) 1296 { 1297 struct damon_sysfs_scheme_regions *tried_regions = 1298 damon_sysfs_scheme_regions_alloc(); 1299 int err; 1300 1301 if (!tried_regions) 1302 return -ENOMEM; 1303 err = kobject_init_and_add(&tried_regions->kobj, 1304 &damon_sysfs_scheme_regions_ktype, &scheme->kobj, 1305 "tried_regions"); 1306 if (err) 1307 kobject_put(&tried_regions->kobj); 1308 else 1309 scheme->tried_regions = tried_regions; 1310 return err; 1311 } 1312 1313 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme) 1314 { 1315 int err; 1316 1317 err = damon_sysfs_scheme_set_access_pattern(scheme); 1318 if (err) 1319 return err; 1320 err = damon_sysfs_scheme_set_quotas(scheme); 1321 if (err) 1322 goto put_access_pattern_out; 1323 err = damon_sysfs_scheme_set_watermarks(scheme); 1324 if (err) 1325 goto put_quotas_access_pattern_out; 1326 err = damon_sysfs_scheme_set_filters(scheme); 1327 if (err) 1328 goto put_watermarks_quotas_access_pattern_out; 1329 err = damon_sysfs_scheme_set_stats(scheme); 1330 if (err) 1331 goto put_filters_watermarks_quotas_access_pattern_out; 1332 err = damon_sysfs_scheme_set_tried_regions(scheme); 1333 if (err) 1334 goto put_tried_regions_out; 1335 return 0; 1336 1337 put_tried_regions_out: 1338 kobject_put(&scheme->tried_regions->kobj); 1339 scheme->tried_regions = NULL; 1340 put_filters_watermarks_quotas_access_pattern_out: 1341 kobject_put(&scheme->filters->kobj); 1342 scheme->filters = NULL; 1343 put_watermarks_quotas_access_pattern_out: 1344 kobject_put(&scheme->watermarks->kobj); 1345 scheme->watermarks = NULL; 1346 put_quotas_access_pattern_out: 1347 kobject_put(&scheme->quotas->kobj); 1348 scheme->quotas = NULL; 1349 put_access_pattern_out: 1350 kobject_put(&scheme->access_pattern->kobj); 1351 scheme->access_pattern = NULL; 1352 return err; 1353 } 1354 1355 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme) 1356 { 1357 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 1358 kobject_put(&scheme->access_pattern->kobj); 1359 damon_sysfs_quotas_rm_dirs(scheme->quotas); 1360 kobject_put(&scheme->quotas->kobj); 1361 kobject_put(&scheme->watermarks->kobj); 1362 damon_sysfs_scheme_filters_rm_dirs(scheme->filters); 1363 kobject_put(&scheme->filters->kobj); 1364 kobject_put(&scheme->stats->kobj); 1365 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions); 1366 kobject_put(&scheme->tried_regions->kobj); 1367 } 1368 1369 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr, 1370 char *buf) 1371 { 1372 struct damon_sysfs_scheme *scheme = container_of(kobj, 1373 struct damon_sysfs_scheme, kobj); 1374 1375 return sysfs_emit(buf, "%s\n", 1376 damon_sysfs_damos_action_strs[scheme->action]); 1377 } 1378 1379 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr, 1380 const char *buf, size_t count) 1381 { 1382 struct damon_sysfs_scheme *scheme = container_of(kobj, 1383 struct damon_sysfs_scheme, kobj); 1384 enum damos_action action; 1385 1386 for (action = 0; action < NR_DAMOS_ACTIONS; action++) { 1387 if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) { 1388 scheme->action = action; 1389 return count; 1390 } 1391 } 1392 return -EINVAL; 1393 } 1394 1395 static ssize_t apply_interval_us_show(struct kobject *kobj, 1396 struct kobj_attribute *attr, char *buf) 1397 { 1398 struct damon_sysfs_scheme *scheme = container_of(kobj, 1399 struct damon_sysfs_scheme, kobj); 1400 1401 return sysfs_emit(buf, "%lu\n", scheme->apply_interval_us); 1402 } 1403 1404 static ssize_t apply_interval_us_store(struct kobject *kobj, 1405 struct kobj_attribute *attr, const char *buf, size_t count) 1406 { 1407 struct damon_sysfs_scheme *scheme = container_of(kobj, 1408 struct damon_sysfs_scheme, kobj); 1409 int err = kstrtoul(buf, 0, &scheme->apply_interval_us); 1410 1411 return err ? err : count; 1412 } 1413 1414 static void damon_sysfs_scheme_release(struct kobject *kobj) 1415 { 1416 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj)); 1417 } 1418 1419 static struct kobj_attribute damon_sysfs_scheme_action_attr = 1420 __ATTR_RW_MODE(action, 0600); 1421 1422 static struct kobj_attribute damon_sysfs_scheme_apply_interval_us_attr = 1423 __ATTR_RW_MODE(apply_interval_us, 0600); 1424 1425 static struct attribute *damon_sysfs_scheme_attrs[] = { 1426 &damon_sysfs_scheme_action_attr.attr, 1427 &damon_sysfs_scheme_apply_interval_us_attr.attr, 1428 NULL, 1429 }; 1430 ATTRIBUTE_GROUPS(damon_sysfs_scheme); 1431 1432 static const struct kobj_type damon_sysfs_scheme_ktype = { 1433 .release = damon_sysfs_scheme_release, 1434 .sysfs_ops = &kobj_sysfs_ops, 1435 .default_groups = damon_sysfs_scheme_groups, 1436 }; 1437 1438 /* 1439 * schemes directory 1440 */ 1441 1442 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void) 1443 { 1444 return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL); 1445 } 1446 1447 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes) 1448 { 1449 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr; 1450 int i; 1451 1452 for (i = 0; i < schemes->nr; i++) { 1453 damon_sysfs_scheme_rm_dirs(schemes_arr[i]); 1454 kobject_put(&schemes_arr[i]->kobj); 1455 } 1456 schemes->nr = 0; 1457 kfree(schemes_arr); 1458 schemes->schemes_arr = NULL; 1459 } 1460 1461 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes, 1462 int nr_schemes) 1463 { 1464 struct damon_sysfs_scheme **schemes_arr, *scheme; 1465 int err, i; 1466 1467 damon_sysfs_schemes_rm_dirs(schemes); 1468 if (!nr_schemes) 1469 return 0; 1470 1471 schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr), 1472 GFP_KERNEL | __GFP_NOWARN); 1473 if (!schemes_arr) 1474 return -ENOMEM; 1475 schemes->schemes_arr = schemes_arr; 1476 1477 for (i = 0; i < nr_schemes; i++) { 1478 /* 1479 * apply_interval_us as 0 means same to aggregation interval 1480 * (same to before-apply_interval behavior) 1481 */ 1482 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT, 0); 1483 if (!scheme) { 1484 damon_sysfs_schemes_rm_dirs(schemes); 1485 return -ENOMEM; 1486 } 1487 1488 err = kobject_init_and_add(&scheme->kobj, 1489 &damon_sysfs_scheme_ktype, &schemes->kobj, 1490 "%d", i); 1491 if (err) 1492 goto out; 1493 err = damon_sysfs_scheme_add_dirs(scheme); 1494 if (err) 1495 goto out; 1496 1497 schemes_arr[i] = scheme; 1498 schemes->nr++; 1499 } 1500 return 0; 1501 1502 out: 1503 damon_sysfs_schemes_rm_dirs(schemes); 1504 kobject_put(&scheme->kobj); 1505 return err; 1506 } 1507 1508 static ssize_t nr_schemes_show(struct kobject *kobj, 1509 struct kobj_attribute *attr, char *buf) 1510 { 1511 struct damon_sysfs_schemes *schemes = container_of(kobj, 1512 struct damon_sysfs_schemes, kobj); 1513 1514 return sysfs_emit(buf, "%d\n", schemes->nr); 1515 } 1516 1517 static ssize_t nr_schemes_store(struct kobject *kobj, 1518 struct kobj_attribute *attr, const char *buf, size_t count) 1519 { 1520 struct damon_sysfs_schemes *schemes; 1521 int nr, err = kstrtoint(buf, 0, &nr); 1522 1523 if (err) 1524 return err; 1525 if (nr < 0) 1526 return -EINVAL; 1527 1528 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj); 1529 1530 if (!mutex_trylock(&damon_sysfs_lock)) 1531 return -EBUSY; 1532 err = damon_sysfs_schemes_add_dirs(schemes, nr); 1533 mutex_unlock(&damon_sysfs_lock); 1534 if (err) 1535 return err; 1536 return count; 1537 } 1538 1539 static void damon_sysfs_schemes_release(struct kobject *kobj) 1540 { 1541 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj)); 1542 } 1543 1544 static struct kobj_attribute damon_sysfs_schemes_nr_attr = 1545 __ATTR_RW_MODE(nr_schemes, 0600); 1546 1547 static struct attribute *damon_sysfs_schemes_attrs[] = { 1548 &damon_sysfs_schemes_nr_attr.attr, 1549 NULL, 1550 }; 1551 ATTRIBUTE_GROUPS(damon_sysfs_schemes); 1552 1553 const struct kobj_type damon_sysfs_schemes_ktype = { 1554 .release = damon_sysfs_schemes_release, 1555 .sysfs_ops = &kobj_sysfs_ops, 1556 .default_groups = damon_sysfs_schemes_groups, 1557 }; 1558 1559 static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg, 1560 char *memcg_path_buf, char *path) 1561 { 1562 #ifdef CONFIG_MEMCG 1563 cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX); 1564 if (sysfs_streq(memcg_path_buf, path)) 1565 return true; 1566 #endif /* CONFIG_MEMCG */ 1567 return false; 1568 } 1569 1570 static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id) 1571 { 1572 struct mem_cgroup *memcg; 1573 char *path; 1574 bool found = false; 1575 1576 if (!memcg_path) 1577 return -EINVAL; 1578 1579 path = kmalloc(sizeof(*path) * PATH_MAX, GFP_KERNEL); 1580 if (!path) 1581 return -ENOMEM; 1582 1583 for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg; 1584 memcg = mem_cgroup_iter(NULL, memcg, NULL)) { 1585 /* skip removed memcg */ 1586 if (!mem_cgroup_id(memcg)) 1587 continue; 1588 if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) { 1589 *id = mem_cgroup_id(memcg); 1590 found = true; 1591 break; 1592 } 1593 } 1594 1595 kfree(path); 1596 return found ? 0 : -EINVAL; 1597 } 1598 1599 static int damon_sysfs_set_scheme_filters(struct damos *scheme, 1600 struct damon_sysfs_scheme_filters *sysfs_filters) 1601 { 1602 int i; 1603 struct damos_filter *filter, *next; 1604 1605 damos_for_each_filter_safe(filter, next, scheme) 1606 damos_destroy_filter(filter); 1607 1608 for (i = 0; i < sysfs_filters->nr; i++) { 1609 struct damon_sysfs_scheme_filter *sysfs_filter = 1610 sysfs_filters->filters_arr[i]; 1611 struct damos_filter *filter = 1612 damos_new_filter(sysfs_filter->type, 1613 sysfs_filter->matching); 1614 int err; 1615 1616 if (!filter) 1617 return -ENOMEM; 1618 if (filter->type == DAMOS_FILTER_TYPE_MEMCG) { 1619 err = damon_sysfs_memcg_path_to_id( 1620 sysfs_filter->memcg_path, 1621 &filter->memcg_id); 1622 if (err) { 1623 damos_destroy_filter(filter); 1624 return err; 1625 } 1626 } else if (filter->type == DAMOS_FILTER_TYPE_ADDR) { 1627 if (sysfs_filter->addr_range.end < 1628 sysfs_filter->addr_range.start) { 1629 damos_destroy_filter(filter); 1630 return -EINVAL; 1631 } 1632 filter->addr_range = sysfs_filter->addr_range; 1633 } else if (filter->type == DAMOS_FILTER_TYPE_TARGET) { 1634 filter->target_idx = sysfs_filter->target_idx; 1635 } 1636 1637 damos_add_filter(scheme, filter); 1638 } 1639 return 0; 1640 } 1641 1642 static struct damos *damon_sysfs_mk_scheme( 1643 struct damon_sysfs_scheme *sysfs_scheme) 1644 { 1645 struct damon_sysfs_access_pattern *access_pattern = 1646 sysfs_scheme->access_pattern; 1647 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; 1648 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; 1649 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; 1650 struct damon_sysfs_scheme_filters *sysfs_filters = 1651 sysfs_scheme->filters; 1652 struct damos *scheme; 1653 int err; 1654 1655 struct damos_access_pattern pattern = { 1656 .min_sz_region = access_pattern->sz->min, 1657 .max_sz_region = access_pattern->sz->max, 1658 .min_nr_accesses = access_pattern->nr_accesses->min, 1659 .max_nr_accesses = access_pattern->nr_accesses->max, 1660 .min_age_region = access_pattern->age->min, 1661 .max_age_region = access_pattern->age->max, 1662 }; 1663 struct damos_quota quota = { 1664 .ms = sysfs_quotas->ms, 1665 .sz = sysfs_quotas->sz, 1666 .reset_interval = sysfs_quotas->reset_interval_ms, 1667 .weight_sz = sysfs_weights->sz, 1668 .weight_nr_accesses = sysfs_weights->nr_accesses, 1669 .weight_age = sysfs_weights->age, 1670 }; 1671 struct damos_watermarks wmarks = { 1672 .metric = sysfs_wmarks->metric, 1673 .interval = sysfs_wmarks->interval_us, 1674 .high = sysfs_wmarks->high, 1675 .mid = sysfs_wmarks->mid, 1676 .low = sysfs_wmarks->low, 1677 }; 1678 1679 scheme = damon_new_scheme(&pattern, sysfs_scheme->action, 1680 sysfs_scheme->apply_interval_us, "a, &wmarks); 1681 if (!scheme) 1682 return NULL; 1683 1684 err = damon_sysfs_set_scheme_filters(scheme, sysfs_filters); 1685 if (err) { 1686 damon_destroy_scheme(scheme); 1687 return NULL; 1688 } 1689 return scheme; 1690 } 1691 1692 static void damon_sysfs_update_scheme(struct damos *scheme, 1693 struct damon_sysfs_scheme *sysfs_scheme) 1694 { 1695 struct damon_sysfs_access_pattern *access_pattern = 1696 sysfs_scheme->access_pattern; 1697 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; 1698 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; 1699 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; 1700 int err; 1701 1702 scheme->pattern.min_sz_region = access_pattern->sz->min; 1703 scheme->pattern.max_sz_region = access_pattern->sz->max; 1704 scheme->pattern.min_nr_accesses = access_pattern->nr_accesses->min; 1705 scheme->pattern.max_nr_accesses = access_pattern->nr_accesses->max; 1706 scheme->pattern.min_age_region = access_pattern->age->min; 1707 scheme->pattern.max_age_region = access_pattern->age->max; 1708 1709 scheme->action = sysfs_scheme->action; 1710 scheme->apply_interval_us = sysfs_scheme->apply_interval_us; 1711 1712 scheme->quota.ms = sysfs_quotas->ms; 1713 scheme->quota.sz = sysfs_quotas->sz; 1714 scheme->quota.reset_interval = sysfs_quotas->reset_interval_ms; 1715 scheme->quota.weight_sz = sysfs_weights->sz; 1716 scheme->quota.weight_nr_accesses = sysfs_weights->nr_accesses; 1717 scheme->quota.weight_age = sysfs_weights->age; 1718 1719 scheme->wmarks.metric = sysfs_wmarks->metric; 1720 scheme->wmarks.interval = sysfs_wmarks->interval_us; 1721 scheme->wmarks.high = sysfs_wmarks->high; 1722 scheme->wmarks.mid = sysfs_wmarks->mid; 1723 scheme->wmarks.low = sysfs_wmarks->low; 1724 1725 err = damon_sysfs_set_scheme_filters(scheme, sysfs_scheme->filters); 1726 if (err) 1727 damon_destroy_scheme(scheme); 1728 } 1729 1730 int damon_sysfs_set_schemes(struct damon_ctx *ctx, 1731 struct damon_sysfs_schemes *sysfs_schemes) 1732 { 1733 struct damos *scheme, *next; 1734 int i = 0; 1735 1736 damon_for_each_scheme_safe(scheme, next, ctx) { 1737 if (i < sysfs_schemes->nr) 1738 damon_sysfs_update_scheme(scheme, 1739 sysfs_schemes->schemes_arr[i]); 1740 else 1741 damon_destroy_scheme(scheme); 1742 i++; 1743 } 1744 1745 for (; i < sysfs_schemes->nr; i++) { 1746 struct damos *scheme, *next; 1747 1748 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]); 1749 if (!scheme) { 1750 damon_for_each_scheme_safe(scheme, next, ctx) 1751 damon_destroy_scheme(scheme); 1752 return -ENOMEM; 1753 } 1754 damon_add_scheme(ctx, scheme); 1755 } 1756 return 0; 1757 } 1758 1759 void damon_sysfs_schemes_update_stats( 1760 struct damon_sysfs_schemes *sysfs_schemes, 1761 struct damon_ctx *ctx) 1762 { 1763 struct damos *scheme; 1764 int schemes_idx = 0; 1765 1766 damon_for_each_scheme(scheme, ctx) { 1767 struct damon_sysfs_stats *sysfs_stats; 1768 1769 /* user could have removed the scheme sysfs dir */ 1770 if (schemes_idx >= sysfs_schemes->nr) 1771 break; 1772 1773 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats; 1774 sysfs_stats->nr_tried = scheme->stat.nr_tried; 1775 sysfs_stats->sz_tried = scheme->stat.sz_tried; 1776 sysfs_stats->nr_applied = scheme->stat.nr_applied; 1777 sysfs_stats->sz_applied = scheme->stat.sz_applied; 1778 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds; 1779 } 1780 } 1781 1782 /* 1783 * damon_sysfs_schemes that need to update its schemes regions dir. Protected 1784 * by damon_sysfs_lock 1785 */ 1786 static struct damon_sysfs_schemes *damon_sysfs_schemes_for_damos_callback; 1787 static int damon_sysfs_schemes_region_idx; 1788 static bool damos_regions_upd_total_bytes_only; 1789 1790 /* 1791 * DAMON callback that called before damos apply. While this callback is 1792 * registered, damon_sysfs_lock should be held to ensure the regions 1793 * directories exist. 1794 */ 1795 static int damon_sysfs_before_damos_apply(struct damon_ctx *ctx, 1796 struct damon_target *t, struct damon_region *r, 1797 struct damos *s) 1798 { 1799 struct damos *scheme; 1800 struct damon_sysfs_scheme_regions *sysfs_regions; 1801 struct damon_sysfs_scheme_region *region; 1802 struct damon_sysfs_schemes *sysfs_schemes = 1803 damon_sysfs_schemes_for_damos_callback; 1804 int schemes_idx = 0; 1805 1806 damon_for_each_scheme(scheme, ctx) { 1807 if (scheme == s) 1808 break; 1809 schemes_idx++; 1810 } 1811 1812 /* user could have removed the scheme sysfs dir */ 1813 if (schemes_idx >= sysfs_schemes->nr) 1814 return 0; 1815 1816 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions; 1817 if (sysfs_regions->upd_status == DAMOS_TRIED_REGIONS_UPD_FINISHED) 1818 return 0; 1819 if (sysfs_regions->upd_status == DAMOS_TRIED_REGIONS_UPD_IDLE) 1820 sysfs_regions->upd_status = DAMOS_TRIED_REGIONS_UPD_STARTED; 1821 sysfs_regions->total_bytes += r->ar.end - r->ar.start; 1822 if (damos_regions_upd_total_bytes_only) 1823 return 0; 1824 1825 region = damon_sysfs_scheme_region_alloc(r); 1826 list_add_tail(®ion->list, &sysfs_regions->regions_list); 1827 sysfs_regions->nr_regions++; 1828 if (kobject_init_and_add(®ion->kobj, 1829 &damon_sysfs_scheme_region_ktype, 1830 &sysfs_regions->kobj, "%d", 1831 damon_sysfs_schemes_region_idx++)) { 1832 kobject_put(®ion->kobj); 1833 } 1834 return 0; 1835 } 1836 1837 /* 1838 * DAMON callback that called after each accesses sampling. While this 1839 * callback is registered, damon_sysfs_lock should be held to ensure the 1840 * regions directories exist. 1841 */ 1842 static int damon_sysfs_after_sampling(struct damon_ctx *ctx) 1843 { 1844 struct damon_sysfs_schemes *sysfs_schemes = 1845 damon_sysfs_schemes_for_damos_callback; 1846 struct damon_sysfs_scheme_regions *sysfs_regions; 1847 int i; 1848 1849 for (i = 0; i < sysfs_schemes->nr; i++) { 1850 sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions; 1851 if (sysfs_regions->upd_status == 1852 DAMOS_TRIED_REGIONS_UPD_STARTED) 1853 sysfs_regions->upd_status = 1854 DAMOS_TRIED_REGIONS_UPD_FINISHED; 1855 } 1856 1857 return 0; 1858 } 1859 1860 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */ 1861 int damon_sysfs_schemes_clear_regions( 1862 struct damon_sysfs_schemes *sysfs_schemes, 1863 struct damon_ctx *ctx) 1864 { 1865 struct damos *scheme; 1866 int schemes_idx = 0; 1867 1868 damon_for_each_scheme(scheme, ctx) { 1869 struct damon_sysfs_scheme *sysfs_scheme; 1870 1871 /* user could have removed the scheme sysfs dir */ 1872 if (schemes_idx >= sysfs_schemes->nr) 1873 break; 1874 1875 sysfs_scheme = sysfs_schemes->schemes_arr[schemes_idx++]; 1876 damon_sysfs_scheme_regions_rm_dirs( 1877 sysfs_scheme->tried_regions); 1878 sysfs_scheme->tried_regions->total_bytes = 0; 1879 } 1880 return 0; 1881 } 1882 1883 static void damos_tried_regions_init_upd_status( 1884 struct damon_sysfs_schemes *sysfs_schemes) 1885 { 1886 int i; 1887 1888 for (i = 0; i < sysfs_schemes->nr; i++) 1889 sysfs_schemes->schemes_arr[i]->tried_regions->upd_status = 1890 DAMOS_TRIED_REGIONS_UPD_IDLE; 1891 } 1892 1893 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */ 1894 int damon_sysfs_schemes_update_regions_start( 1895 struct damon_sysfs_schemes *sysfs_schemes, 1896 struct damon_ctx *ctx, bool total_bytes_only) 1897 { 1898 damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx); 1899 damon_sysfs_schemes_for_damos_callback = sysfs_schemes; 1900 damos_tried_regions_init_upd_status(sysfs_schemes); 1901 damos_regions_upd_total_bytes_only = total_bytes_only; 1902 ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply; 1903 ctx->callback.after_sampling = damon_sysfs_after_sampling; 1904 return 0; 1905 } 1906 1907 bool damos_sysfs_regions_upd_done(void) 1908 { 1909 struct damon_sysfs_schemes *sysfs_schemes = 1910 damon_sysfs_schemes_for_damos_callback; 1911 struct damon_sysfs_scheme_regions *sysfs_regions; 1912 int i; 1913 1914 for (i = 0; i < sysfs_schemes->nr; i++) { 1915 sysfs_regions = sysfs_schemes->schemes_arr[i]->tried_regions; 1916 if (sysfs_regions->upd_status != 1917 DAMOS_TRIED_REGIONS_UPD_FINISHED) 1918 return false; 1919 } 1920 return true; 1921 } 1922 1923 /* 1924 * Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock. Caller 1925 * should unlock damon_sysfs_lock which held before 1926 * damon_sysfs_schemes_update_regions_start() 1927 */ 1928 int damon_sysfs_schemes_update_regions_stop(struct damon_ctx *ctx) 1929 { 1930 damon_sysfs_schemes_for_damos_callback = NULL; 1931 ctx->callback.before_damos_apply = NULL; 1932 ctx->callback.after_sampling = NULL; 1933 damon_sysfs_schemes_region_idx = 0; 1934 return 0; 1935 } 1936