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