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