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; 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 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 struct damon_sysfs_scheme_regions { 117 struct kobject kobj; 118 struct list_head regions_list; 119 int nr_regions; 120 }; 121 122 static struct damon_sysfs_scheme_regions * 123 damon_sysfs_scheme_regions_alloc(void) 124 { 125 struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions), 126 GFP_KERNEL); 127 128 regions->kobj = (struct kobject){}; 129 INIT_LIST_HEAD(®ions->regions_list); 130 regions->nr_regions = 0; 131 return regions; 132 } 133 134 static void damon_sysfs_scheme_regions_rm_dirs( 135 struct damon_sysfs_scheme_regions *regions) 136 { 137 struct damon_sysfs_scheme_region *r, *next; 138 139 list_for_each_entry_safe(r, next, ®ions->regions_list, list) { 140 /* release function deletes it from the list */ 141 kobject_put(&r->kobj); 142 regions->nr_regions--; 143 } 144 } 145 146 static void damon_sysfs_scheme_regions_release(struct kobject *kobj) 147 { 148 kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj)); 149 } 150 151 static struct attribute *damon_sysfs_scheme_regions_attrs[] = { 152 NULL, 153 }; 154 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions); 155 156 static struct kobj_type damon_sysfs_scheme_regions_ktype = { 157 .release = damon_sysfs_scheme_regions_release, 158 .sysfs_ops = &kobj_sysfs_ops, 159 .default_groups = damon_sysfs_scheme_regions_groups, 160 }; 161 162 /* 163 * schemes/stats directory 164 */ 165 166 struct damon_sysfs_stats { 167 struct kobject kobj; 168 unsigned long nr_tried; 169 unsigned long sz_tried; 170 unsigned long nr_applied; 171 unsigned long sz_applied; 172 unsigned long qt_exceeds; 173 }; 174 175 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void) 176 { 177 return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL); 178 } 179 180 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr, 181 char *buf) 182 { 183 struct damon_sysfs_stats *stats = container_of(kobj, 184 struct damon_sysfs_stats, kobj); 185 186 return sysfs_emit(buf, "%lu\n", stats->nr_tried); 187 } 188 189 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr, 190 char *buf) 191 { 192 struct damon_sysfs_stats *stats = container_of(kobj, 193 struct damon_sysfs_stats, kobj); 194 195 return sysfs_emit(buf, "%lu\n", stats->sz_tried); 196 } 197 198 static ssize_t nr_applied_show(struct kobject *kobj, 199 struct kobj_attribute *attr, char *buf) 200 { 201 struct damon_sysfs_stats *stats = container_of(kobj, 202 struct damon_sysfs_stats, kobj); 203 204 return sysfs_emit(buf, "%lu\n", stats->nr_applied); 205 } 206 207 static ssize_t sz_applied_show(struct kobject *kobj, 208 struct kobj_attribute *attr, char *buf) 209 { 210 struct damon_sysfs_stats *stats = container_of(kobj, 211 struct damon_sysfs_stats, kobj); 212 213 return sysfs_emit(buf, "%lu\n", stats->sz_applied); 214 } 215 216 static ssize_t qt_exceeds_show(struct kobject *kobj, 217 struct kobj_attribute *attr, char *buf) 218 { 219 struct damon_sysfs_stats *stats = container_of(kobj, 220 struct damon_sysfs_stats, kobj); 221 222 return sysfs_emit(buf, "%lu\n", stats->qt_exceeds); 223 } 224 225 static void damon_sysfs_stats_release(struct kobject *kobj) 226 { 227 kfree(container_of(kobj, struct damon_sysfs_stats, kobj)); 228 } 229 230 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr = 231 __ATTR_RO_MODE(nr_tried, 0400); 232 233 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr = 234 __ATTR_RO_MODE(sz_tried, 0400); 235 236 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr = 237 __ATTR_RO_MODE(nr_applied, 0400); 238 239 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr = 240 __ATTR_RO_MODE(sz_applied, 0400); 241 242 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr = 243 __ATTR_RO_MODE(qt_exceeds, 0400); 244 245 static struct attribute *damon_sysfs_stats_attrs[] = { 246 &damon_sysfs_stats_nr_tried_attr.attr, 247 &damon_sysfs_stats_sz_tried_attr.attr, 248 &damon_sysfs_stats_nr_applied_attr.attr, 249 &damon_sysfs_stats_sz_applied_attr.attr, 250 &damon_sysfs_stats_qt_exceeds_attr.attr, 251 NULL, 252 }; 253 ATTRIBUTE_GROUPS(damon_sysfs_stats); 254 255 static struct kobj_type damon_sysfs_stats_ktype = { 256 .release = damon_sysfs_stats_release, 257 .sysfs_ops = &kobj_sysfs_ops, 258 .default_groups = damon_sysfs_stats_groups, 259 }; 260 261 /* 262 * watermarks directory 263 */ 264 265 struct damon_sysfs_watermarks { 266 struct kobject kobj; 267 enum damos_wmark_metric metric; 268 unsigned long interval_us; 269 unsigned long high; 270 unsigned long mid; 271 unsigned long low; 272 }; 273 274 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc( 275 enum damos_wmark_metric metric, unsigned long interval_us, 276 unsigned long high, unsigned long mid, unsigned long low) 277 { 278 struct damon_sysfs_watermarks *watermarks = kmalloc( 279 sizeof(*watermarks), GFP_KERNEL); 280 281 if (!watermarks) 282 return NULL; 283 watermarks->kobj = (struct kobject){}; 284 watermarks->metric = metric; 285 watermarks->interval_us = interval_us; 286 watermarks->high = high; 287 watermarks->mid = mid; 288 watermarks->low = low; 289 return watermarks; 290 } 291 292 /* Should match with enum damos_wmark_metric */ 293 static const char * const damon_sysfs_wmark_metric_strs[] = { 294 "none", 295 "free_mem_rate", 296 }; 297 298 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr, 299 char *buf) 300 { 301 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 302 struct damon_sysfs_watermarks, kobj); 303 304 return sysfs_emit(buf, "%s\n", 305 damon_sysfs_wmark_metric_strs[watermarks->metric]); 306 } 307 308 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr, 309 const char *buf, size_t count) 310 { 311 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 312 struct damon_sysfs_watermarks, kobj); 313 enum damos_wmark_metric metric; 314 315 for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) { 316 if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) { 317 watermarks->metric = metric; 318 return count; 319 } 320 } 321 return -EINVAL; 322 } 323 324 static ssize_t interval_us_show(struct kobject *kobj, 325 struct kobj_attribute *attr, char *buf) 326 { 327 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 328 struct damon_sysfs_watermarks, kobj); 329 330 return sysfs_emit(buf, "%lu\n", watermarks->interval_us); 331 } 332 333 static ssize_t interval_us_store(struct kobject *kobj, 334 struct kobj_attribute *attr, const char *buf, size_t count) 335 { 336 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 337 struct damon_sysfs_watermarks, kobj); 338 int err = kstrtoul(buf, 0, &watermarks->interval_us); 339 340 return err ? err : count; 341 } 342 343 static ssize_t high_show(struct kobject *kobj, 344 struct kobj_attribute *attr, char *buf) 345 { 346 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 347 struct damon_sysfs_watermarks, kobj); 348 349 return sysfs_emit(buf, "%lu\n", watermarks->high); 350 } 351 352 static ssize_t high_store(struct kobject *kobj, 353 struct kobj_attribute *attr, const char *buf, size_t count) 354 { 355 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 356 struct damon_sysfs_watermarks, kobj); 357 int err = kstrtoul(buf, 0, &watermarks->high); 358 359 return err ? err : count; 360 } 361 362 static ssize_t mid_show(struct kobject *kobj, 363 struct kobj_attribute *attr, char *buf) 364 { 365 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 366 struct damon_sysfs_watermarks, kobj); 367 368 return sysfs_emit(buf, "%lu\n", watermarks->mid); 369 } 370 371 static ssize_t mid_store(struct kobject *kobj, 372 struct kobj_attribute *attr, const char *buf, size_t count) 373 { 374 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 375 struct damon_sysfs_watermarks, kobj); 376 int err = kstrtoul(buf, 0, &watermarks->mid); 377 378 return err ? err : count; 379 } 380 381 static ssize_t low_show(struct kobject *kobj, 382 struct kobj_attribute *attr, char *buf) 383 { 384 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 385 struct damon_sysfs_watermarks, kobj); 386 387 return sysfs_emit(buf, "%lu\n", watermarks->low); 388 } 389 390 static ssize_t low_store(struct kobject *kobj, 391 struct kobj_attribute *attr, const char *buf, size_t count) 392 { 393 struct damon_sysfs_watermarks *watermarks = container_of(kobj, 394 struct damon_sysfs_watermarks, kobj); 395 int err = kstrtoul(buf, 0, &watermarks->low); 396 397 return err ? err : count; 398 } 399 400 static void damon_sysfs_watermarks_release(struct kobject *kobj) 401 { 402 kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj)); 403 } 404 405 static struct kobj_attribute damon_sysfs_watermarks_metric_attr = 406 __ATTR_RW_MODE(metric, 0600); 407 408 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr = 409 __ATTR_RW_MODE(interval_us, 0600); 410 411 static struct kobj_attribute damon_sysfs_watermarks_high_attr = 412 __ATTR_RW_MODE(high, 0600); 413 414 static struct kobj_attribute damon_sysfs_watermarks_mid_attr = 415 __ATTR_RW_MODE(mid, 0600); 416 417 static struct kobj_attribute damon_sysfs_watermarks_low_attr = 418 __ATTR_RW_MODE(low, 0600); 419 420 static struct attribute *damon_sysfs_watermarks_attrs[] = { 421 &damon_sysfs_watermarks_metric_attr.attr, 422 &damon_sysfs_watermarks_interval_us_attr.attr, 423 &damon_sysfs_watermarks_high_attr.attr, 424 &damon_sysfs_watermarks_mid_attr.attr, 425 &damon_sysfs_watermarks_low_attr.attr, 426 NULL, 427 }; 428 ATTRIBUTE_GROUPS(damon_sysfs_watermarks); 429 430 static struct kobj_type damon_sysfs_watermarks_ktype = { 431 .release = damon_sysfs_watermarks_release, 432 .sysfs_ops = &kobj_sysfs_ops, 433 .default_groups = damon_sysfs_watermarks_groups, 434 }; 435 436 /* 437 * scheme/weights directory 438 */ 439 440 struct damon_sysfs_weights { 441 struct kobject kobj; 442 unsigned int sz; 443 unsigned int nr_accesses; 444 unsigned int age; 445 }; 446 447 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz, 448 unsigned int nr_accesses, unsigned int age) 449 { 450 struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights), 451 GFP_KERNEL); 452 453 if (!weights) 454 return NULL; 455 weights->kobj = (struct kobject){}; 456 weights->sz = sz; 457 weights->nr_accesses = nr_accesses; 458 weights->age = age; 459 return weights; 460 } 461 462 static ssize_t sz_permil_show(struct kobject *kobj, 463 struct kobj_attribute *attr, char *buf) 464 { 465 struct damon_sysfs_weights *weights = container_of(kobj, 466 struct damon_sysfs_weights, kobj); 467 468 return sysfs_emit(buf, "%u\n", weights->sz); 469 } 470 471 static ssize_t sz_permil_store(struct kobject *kobj, 472 struct kobj_attribute *attr, const char *buf, size_t count) 473 { 474 struct damon_sysfs_weights *weights = container_of(kobj, 475 struct damon_sysfs_weights, kobj); 476 int err = kstrtouint(buf, 0, &weights->sz); 477 478 return err ? err : count; 479 } 480 481 static ssize_t nr_accesses_permil_show(struct kobject *kobj, 482 struct kobj_attribute *attr, char *buf) 483 { 484 struct damon_sysfs_weights *weights = container_of(kobj, 485 struct damon_sysfs_weights, kobj); 486 487 return sysfs_emit(buf, "%u\n", weights->nr_accesses); 488 } 489 490 static ssize_t nr_accesses_permil_store(struct kobject *kobj, 491 struct kobj_attribute *attr, const char *buf, size_t count) 492 { 493 struct damon_sysfs_weights *weights = container_of(kobj, 494 struct damon_sysfs_weights, kobj); 495 int err = kstrtouint(buf, 0, &weights->nr_accesses); 496 497 return err ? err : count; 498 } 499 500 static ssize_t age_permil_show(struct kobject *kobj, 501 struct kobj_attribute *attr, char *buf) 502 { 503 struct damon_sysfs_weights *weights = container_of(kobj, 504 struct damon_sysfs_weights, kobj); 505 506 return sysfs_emit(buf, "%u\n", weights->age); 507 } 508 509 static ssize_t age_permil_store(struct kobject *kobj, 510 struct kobj_attribute *attr, const char *buf, size_t count) 511 { 512 struct damon_sysfs_weights *weights = container_of(kobj, 513 struct damon_sysfs_weights, kobj); 514 int err = kstrtouint(buf, 0, &weights->age); 515 516 return err ? err : count; 517 } 518 519 static void damon_sysfs_weights_release(struct kobject *kobj) 520 { 521 kfree(container_of(kobj, struct damon_sysfs_weights, kobj)); 522 } 523 524 static struct kobj_attribute damon_sysfs_weights_sz_attr = 525 __ATTR_RW_MODE(sz_permil, 0600); 526 527 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr = 528 __ATTR_RW_MODE(nr_accesses_permil, 0600); 529 530 static struct kobj_attribute damon_sysfs_weights_age_attr = 531 __ATTR_RW_MODE(age_permil, 0600); 532 533 static struct attribute *damon_sysfs_weights_attrs[] = { 534 &damon_sysfs_weights_sz_attr.attr, 535 &damon_sysfs_weights_nr_accesses_attr.attr, 536 &damon_sysfs_weights_age_attr.attr, 537 NULL, 538 }; 539 ATTRIBUTE_GROUPS(damon_sysfs_weights); 540 541 static struct kobj_type damon_sysfs_weights_ktype = { 542 .release = damon_sysfs_weights_release, 543 .sysfs_ops = &kobj_sysfs_ops, 544 .default_groups = damon_sysfs_weights_groups, 545 }; 546 547 /* 548 * quotas directory 549 */ 550 551 struct damon_sysfs_quotas { 552 struct kobject kobj; 553 struct damon_sysfs_weights *weights; 554 unsigned long ms; 555 unsigned long sz; 556 unsigned long reset_interval_ms; 557 }; 558 559 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void) 560 { 561 return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL); 562 } 563 564 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas) 565 { 566 struct damon_sysfs_weights *weights; 567 int err; 568 569 weights = damon_sysfs_weights_alloc(0, 0, 0); 570 if (!weights) 571 return -ENOMEM; 572 573 err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype, 574 "as->kobj, "weights"); 575 if (err) 576 kobject_put(&weights->kobj); 577 else 578 quotas->weights = weights; 579 return err; 580 } 581 582 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas) 583 { 584 kobject_put("as->weights->kobj); 585 } 586 587 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr, 588 char *buf) 589 { 590 struct damon_sysfs_quotas *quotas = container_of(kobj, 591 struct damon_sysfs_quotas, kobj); 592 593 return sysfs_emit(buf, "%lu\n", quotas->ms); 594 } 595 596 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr, 597 const char *buf, size_t count) 598 { 599 struct damon_sysfs_quotas *quotas = container_of(kobj, 600 struct damon_sysfs_quotas, kobj); 601 int err = kstrtoul(buf, 0, "as->ms); 602 603 if (err) 604 return -EINVAL; 605 return count; 606 } 607 608 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr, 609 char *buf) 610 { 611 struct damon_sysfs_quotas *quotas = container_of(kobj, 612 struct damon_sysfs_quotas, kobj); 613 614 return sysfs_emit(buf, "%lu\n", quotas->sz); 615 } 616 617 static ssize_t bytes_store(struct kobject *kobj, 618 struct kobj_attribute *attr, const char *buf, size_t count) 619 { 620 struct damon_sysfs_quotas *quotas = container_of(kobj, 621 struct damon_sysfs_quotas, kobj); 622 int err = kstrtoul(buf, 0, "as->sz); 623 624 if (err) 625 return -EINVAL; 626 return count; 627 } 628 629 static ssize_t reset_interval_ms_show(struct kobject *kobj, 630 struct kobj_attribute *attr, char *buf) 631 { 632 struct damon_sysfs_quotas *quotas = container_of(kobj, 633 struct damon_sysfs_quotas, kobj); 634 635 return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms); 636 } 637 638 static ssize_t reset_interval_ms_store(struct kobject *kobj, 639 struct kobj_attribute *attr, const char *buf, size_t count) 640 { 641 struct damon_sysfs_quotas *quotas = container_of(kobj, 642 struct damon_sysfs_quotas, kobj); 643 int err = kstrtoul(buf, 0, "as->reset_interval_ms); 644 645 if (err) 646 return -EINVAL; 647 return count; 648 } 649 650 static void damon_sysfs_quotas_release(struct kobject *kobj) 651 { 652 kfree(container_of(kobj, struct damon_sysfs_quotas, kobj)); 653 } 654 655 static struct kobj_attribute damon_sysfs_quotas_ms_attr = 656 __ATTR_RW_MODE(ms, 0600); 657 658 static struct kobj_attribute damon_sysfs_quotas_sz_attr = 659 __ATTR_RW_MODE(bytes, 0600); 660 661 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr = 662 __ATTR_RW_MODE(reset_interval_ms, 0600); 663 664 static struct attribute *damon_sysfs_quotas_attrs[] = { 665 &damon_sysfs_quotas_ms_attr.attr, 666 &damon_sysfs_quotas_sz_attr.attr, 667 &damon_sysfs_quotas_reset_interval_ms_attr.attr, 668 NULL, 669 }; 670 ATTRIBUTE_GROUPS(damon_sysfs_quotas); 671 672 static struct kobj_type damon_sysfs_quotas_ktype = { 673 .release = damon_sysfs_quotas_release, 674 .sysfs_ops = &kobj_sysfs_ops, 675 .default_groups = damon_sysfs_quotas_groups, 676 }; 677 678 /* 679 * access_pattern directory 680 */ 681 682 struct damon_sysfs_access_pattern { 683 struct kobject kobj; 684 struct damon_sysfs_ul_range *sz; 685 struct damon_sysfs_ul_range *nr_accesses; 686 struct damon_sysfs_ul_range *age; 687 }; 688 689 static 690 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void) 691 { 692 struct damon_sysfs_access_pattern *access_pattern = 693 kmalloc(sizeof(*access_pattern), GFP_KERNEL); 694 695 if (!access_pattern) 696 return NULL; 697 access_pattern->kobj = (struct kobject){}; 698 return access_pattern; 699 } 700 701 static int damon_sysfs_access_pattern_add_range_dir( 702 struct damon_sysfs_access_pattern *access_pattern, 703 struct damon_sysfs_ul_range **range_dir_ptr, 704 char *name) 705 { 706 struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0); 707 int err; 708 709 if (!range) 710 return -ENOMEM; 711 err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype, 712 &access_pattern->kobj, name); 713 if (err) 714 kobject_put(&range->kobj); 715 else 716 *range_dir_ptr = range; 717 return err; 718 } 719 720 static int damon_sysfs_access_pattern_add_dirs( 721 struct damon_sysfs_access_pattern *access_pattern) 722 { 723 int err; 724 725 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 726 &access_pattern->sz, "sz"); 727 if (err) 728 goto put_sz_out; 729 730 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 731 &access_pattern->nr_accesses, "nr_accesses"); 732 if (err) 733 goto put_nr_accesses_sz_out; 734 735 err = damon_sysfs_access_pattern_add_range_dir(access_pattern, 736 &access_pattern->age, "age"); 737 if (err) 738 goto put_age_nr_accesses_sz_out; 739 return 0; 740 741 put_age_nr_accesses_sz_out: 742 kobject_put(&access_pattern->age->kobj); 743 access_pattern->age = NULL; 744 put_nr_accesses_sz_out: 745 kobject_put(&access_pattern->nr_accesses->kobj); 746 access_pattern->nr_accesses = NULL; 747 put_sz_out: 748 kobject_put(&access_pattern->sz->kobj); 749 access_pattern->sz = NULL; 750 return err; 751 } 752 753 static void damon_sysfs_access_pattern_rm_dirs( 754 struct damon_sysfs_access_pattern *access_pattern) 755 { 756 kobject_put(&access_pattern->sz->kobj); 757 kobject_put(&access_pattern->nr_accesses->kobj); 758 kobject_put(&access_pattern->age->kobj); 759 } 760 761 static void damon_sysfs_access_pattern_release(struct kobject *kobj) 762 { 763 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj)); 764 } 765 766 static struct attribute *damon_sysfs_access_pattern_attrs[] = { 767 NULL, 768 }; 769 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern); 770 771 static struct kobj_type damon_sysfs_access_pattern_ktype = { 772 .release = damon_sysfs_access_pattern_release, 773 .sysfs_ops = &kobj_sysfs_ops, 774 .default_groups = damon_sysfs_access_pattern_groups, 775 }; 776 777 /* 778 * scheme directory 779 */ 780 781 struct damon_sysfs_scheme { 782 struct kobject kobj; 783 enum damos_action action; 784 struct damon_sysfs_access_pattern *access_pattern; 785 struct damon_sysfs_quotas *quotas; 786 struct damon_sysfs_watermarks *watermarks; 787 struct damon_sysfs_stats *stats; 788 struct damon_sysfs_scheme_regions *tried_regions; 789 }; 790 791 /* This should match with enum damos_action */ 792 static const char * const damon_sysfs_damos_action_strs[] = { 793 "willneed", 794 "cold", 795 "pageout", 796 "hugepage", 797 "nohugepage", 798 "lru_prio", 799 "lru_deprio", 800 "stat", 801 }; 802 803 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc( 804 enum damos_action action) 805 { 806 struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme), 807 GFP_KERNEL); 808 809 if (!scheme) 810 return NULL; 811 scheme->kobj = (struct kobject){}; 812 scheme->action = action; 813 return scheme; 814 } 815 816 static int damon_sysfs_scheme_set_access_pattern( 817 struct damon_sysfs_scheme *scheme) 818 { 819 struct damon_sysfs_access_pattern *access_pattern; 820 int err; 821 822 access_pattern = damon_sysfs_access_pattern_alloc(); 823 if (!access_pattern) 824 return -ENOMEM; 825 err = kobject_init_and_add(&access_pattern->kobj, 826 &damon_sysfs_access_pattern_ktype, &scheme->kobj, 827 "access_pattern"); 828 if (err) 829 goto out; 830 err = damon_sysfs_access_pattern_add_dirs(access_pattern); 831 if (err) 832 goto out; 833 scheme->access_pattern = access_pattern; 834 return 0; 835 836 out: 837 kobject_put(&access_pattern->kobj); 838 return err; 839 } 840 841 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme) 842 { 843 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc(); 844 int err; 845 846 if (!quotas) 847 return -ENOMEM; 848 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype, 849 &scheme->kobj, "quotas"); 850 if (err) 851 goto out; 852 err = damon_sysfs_quotas_add_dirs(quotas); 853 if (err) 854 goto out; 855 scheme->quotas = quotas; 856 return 0; 857 858 out: 859 kobject_put("as->kobj); 860 return err; 861 } 862 863 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme) 864 { 865 struct damon_sysfs_watermarks *watermarks = 866 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0); 867 int err; 868 869 if (!watermarks) 870 return -ENOMEM; 871 err = kobject_init_and_add(&watermarks->kobj, 872 &damon_sysfs_watermarks_ktype, &scheme->kobj, 873 "watermarks"); 874 if (err) 875 kobject_put(&watermarks->kobj); 876 else 877 scheme->watermarks = watermarks; 878 return err; 879 } 880 881 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme) 882 { 883 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc(); 884 int err; 885 886 if (!stats) 887 return -ENOMEM; 888 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype, 889 &scheme->kobj, "stats"); 890 if (err) 891 kobject_put(&stats->kobj); 892 else 893 scheme->stats = stats; 894 return err; 895 } 896 897 static int damon_sysfs_scheme_set_tried_regions( 898 struct damon_sysfs_scheme *scheme) 899 { 900 struct damon_sysfs_scheme_regions *tried_regions = 901 damon_sysfs_scheme_regions_alloc(); 902 int err; 903 904 if (!tried_regions) 905 return -ENOMEM; 906 err = kobject_init_and_add(&tried_regions->kobj, 907 &damon_sysfs_scheme_regions_ktype, &scheme->kobj, 908 "tried_regions"); 909 if (err) 910 kobject_put(&tried_regions->kobj); 911 else 912 scheme->tried_regions = tried_regions; 913 return err; 914 } 915 916 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme) 917 { 918 int err; 919 920 err = damon_sysfs_scheme_set_access_pattern(scheme); 921 if (err) 922 return err; 923 err = damon_sysfs_scheme_set_quotas(scheme); 924 if (err) 925 goto put_access_pattern_out; 926 err = damon_sysfs_scheme_set_watermarks(scheme); 927 if (err) 928 goto put_quotas_access_pattern_out; 929 err = damon_sysfs_scheme_set_stats(scheme); 930 if (err) 931 goto put_watermarks_quotas_access_pattern_out; 932 err = damon_sysfs_scheme_set_tried_regions(scheme); 933 if (err) 934 goto put_tried_regions_out; 935 return 0; 936 937 put_tried_regions_out: 938 kobject_put(&scheme->tried_regions->kobj); 939 scheme->tried_regions = NULL; 940 put_watermarks_quotas_access_pattern_out: 941 kobject_put(&scheme->watermarks->kobj); 942 scheme->watermarks = NULL; 943 put_quotas_access_pattern_out: 944 kobject_put(&scheme->quotas->kobj); 945 scheme->quotas = NULL; 946 put_access_pattern_out: 947 kobject_put(&scheme->access_pattern->kobj); 948 scheme->access_pattern = NULL; 949 return err; 950 } 951 952 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme) 953 { 954 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern); 955 kobject_put(&scheme->access_pattern->kobj); 956 damon_sysfs_quotas_rm_dirs(scheme->quotas); 957 kobject_put(&scheme->quotas->kobj); 958 kobject_put(&scheme->watermarks->kobj); 959 kobject_put(&scheme->stats->kobj); 960 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions); 961 kobject_put(&scheme->tried_regions->kobj); 962 } 963 964 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr, 965 char *buf) 966 { 967 struct damon_sysfs_scheme *scheme = container_of(kobj, 968 struct damon_sysfs_scheme, kobj); 969 970 return sysfs_emit(buf, "%s\n", 971 damon_sysfs_damos_action_strs[scheme->action]); 972 } 973 974 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr, 975 const char *buf, size_t count) 976 { 977 struct damon_sysfs_scheme *scheme = container_of(kobj, 978 struct damon_sysfs_scheme, kobj); 979 enum damos_action action; 980 981 for (action = 0; action < NR_DAMOS_ACTIONS; action++) { 982 if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) { 983 scheme->action = action; 984 return count; 985 } 986 } 987 return -EINVAL; 988 } 989 990 static void damon_sysfs_scheme_release(struct kobject *kobj) 991 { 992 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj)); 993 } 994 995 static struct kobj_attribute damon_sysfs_scheme_action_attr = 996 __ATTR_RW_MODE(action, 0600); 997 998 static struct attribute *damon_sysfs_scheme_attrs[] = { 999 &damon_sysfs_scheme_action_attr.attr, 1000 NULL, 1001 }; 1002 ATTRIBUTE_GROUPS(damon_sysfs_scheme); 1003 1004 static struct kobj_type damon_sysfs_scheme_ktype = { 1005 .release = damon_sysfs_scheme_release, 1006 .sysfs_ops = &kobj_sysfs_ops, 1007 .default_groups = damon_sysfs_scheme_groups, 1008 }; 1009 1010 /* 1011 * schemes directory 1012 */ 1013 1014 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void) 1015 { 1016 return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL); 1017 } 1018 1019 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes) 1020 { 1021 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr; 1022 int i; 1023 1024 for (i = 0; i < schemes->nr; i++) { 1025 damon_sysfs_scheme_rm_dirs(schemes_arr[i]); 1026 kobject_put(&schemes_arr[i]->kobj); 1027 } 1028 schemes->nr = 0; 1029 kfree(schemes_arr); 1030 schemes->schemes_arr = NULL; 1031 } 1032 1033 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes, 1034 int nr_schemes) 1035 { 1036 struct damon_sysfs_scheme **schemes_arr, *scheme; 1037 int err, i; 1038 1039 damon_sysfs_schemes_rm_dirs(schemes); 1040 if (!nr_schemes) 1041 return 0; 1042 1043 schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr), 1044 GFP_KERNEL | __GFP_NOWARN); 1045 if (!schemes_arr) 1046 return -ENOMEM; 1047 schemes->schemes_arr = schemes_arr; 1048 1049 for (i = 0; i < nr_schemes; i++) { 1050 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT); 1051 if (!scheme) { 1052 damon_sysfs_schemes_rm_dirs(schemes); 1053 return -ENOMEM; 1054 } 1055 1056 err = kobject_init_and_add(&scheme->kobj, 1057 &damon_sysfs_scheme_ktype, &schemes->kobj, 1058 "%d", i); 1059 if (err) 1060 goto out; 1061 err = damon_sysfs_scheme_add_dirs(scheme); 1062 if (err) 1063 goto out; 1064 1065 schemes_arr[i] = scheme; 1066 schemes->nr++; 1067 } 1068 return 0; 1069 1070 out: 1071 damon_sysfs_schemes_rm_dirs(schemes); 1072 kobject_put(&scheme->kobj); 1073 return err; 1074 } 1075 1076 static ssize_t nr_schemes_show(struct kobject *kobj, 1077 struct kobj_attribute *attr, char *buf) 1078 { 1079 struct damon_sysfs_schemes *schemes = container_of(kobj, 1080 struct damon_sysfs_schemes, kobj); 1081 1082 return sysfs_emit(buf, "%d\n", schemes->nr); 1083 } 1084 1085 static ssize_t nr_schemes_store(struct kobject *kobj, 1086 struct kobj_attribute *attr, const char *buf, size_t count) 1087 { 1088 struct damon_sysfs_schemes *schemes; 1089 int nr, err = kstrtoint(buf, 0, &nr); 1090 1091 if (err) 1092 return err; 1093 if (nr < 0) 1094 return -EINVAL; 1095 1096 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj); 1097 1098 if (!mutex_trylock(&damon_sysfs_lock)) 1099 return -EBUSY; 1100 err = damon_sysfs_schemes_add_dirs(schemes, nr); 1101 mutex_unlock(&damon_sysfs_lock); 1102 if (err) 1103 return err; 1104 return count; 1105 } 1106 1107 static void damon_sysfs_schemes_release(struct kobject *kobj) 1108 { 1109 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj)); 1110 } 1111 1112 static struct kobj_attribute damon_sysfs_schemes_nr_attr = 1113 __ATTR_RW_MODE(nr_schemes, 0600); 1114 1115 static struct attribute *damon_sysfs_schemes_attrs[] = { 1116 &damon_sysfs_schemes_nr_attr.attr, 1117 NULL, 1118 }; 1119 ATTRIBUTE_GROUPS(damon_sysfs_schemes); 1120 1121 struct kobj_type damon_sysfs_schemes_ktype = { 1122 .release = damon_sysfs_schemes_release, 1123 .sysfs_ops = &kobj_sysfs_ops, 1124 .default_groups = damon_sysfs_schemes_groups, 1125 }; 1126 1127 static struct damos *damon_sysfs_mk_scheme( 1128 struct damon_sysfs_scheme *sysfs_scheme) 1129 { 1130 struct damon_sysfs_access_pattern *access_pattern = 1131 sysfs_scheme->access_pattern; 1132 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; 1133 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; 1134 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; 1135 1136 struct damos_access_pattern pattern = { 1137 .min_sz_region = access_pattern->sz->min, 1138 .max_sz_region = access_pattern->sz->max, 1139 .min_nr_accesses = access_pattern->nr_accesses->min, 1140 .max_nr_accesses = access_pattern->nr_accesses->max, 1141 .min_age_region = access_pattern->age->min, 1142 .max_age_region = access_pattern->age->max, 1143 }; 1144 struct damos_quota quota = { 1145 .ms = sysfs_quotas->ms, 1146 .sz = sysfs_quotas->sz, 1147 .reset_interval = sysfs_quotas->reset_interval_ms, 1148 .weight_sz = sysfs_weights->sz, 1149 .weight_nr_accesses = sysfs_weights->nr_accesses, 1150 .weight_age = sysfs_weights->age, 1151 }; 1152 struct damos_watermarks wmarks = { 1153 .metric = sysfs_wmarks->metric, 1154 .interval = sysfs_wmarks->interval_us, 1155 .high = sysfs_wmarks->high, 1156 .mid = sysfs_wmarks->mid, 1157 .low = sysfs_wmarks->low, 1158 }; 1159 1160 return damon_new_scheme(&pattern, sysfs_scheme->action, "a, 1161 &wmarks); 1162 } 1163 1164 static void damon_sysfs_update_scheme(struct damos *scheme, 1165 struct damon_sysfs_scheme *sysfs_scheme) 1166 { 1167 struct damon_sysfs_access_pattern *access_pattern = 1168 sysfs_scheme->access_pattern; 1169 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas; 1170 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights; 1171 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks; 1172 1173 scheme->pattern.min_sz_region = access_pattern->sz->min; 1174 scheme->pattern.max_sz_region = access_pattern->sz->max; 1175 scheme->pattern.min_nr_accesses = access_pattern->nr_accesses->min; 1176 scheme->pattern.max_nr_accesses = access_pattern->nr_accesses->max; 1177 scheme->pattern.min_age_region = access_pattern->age->min; 1178 scheme->pattern.max_age_region = access_pattern->age->max; 1179 1180 scheme->action = sysfs_scheme->action; 1181 1182 scheme->quota.ms = sysfs_quotas->ms; 1183 scheme->quota.sz = sysfs_quotas->sz; 1184 scheme->quota.reset_interval = sysfs_quotas->reset_interval_ms; 1185 scheme->quota.weight_sz = sysfs_weights->sz; 1186 scheme->quota.weight_nr_accesses = sysfs_weights->nr_accesses; 1187 scheme->quota.weight_age = sysfs_weights->age; 1188 1189 scheme->wmarks.metric = sysfs_wmarks->metric; 1190 scheme->wmarks.interval = sysfs_wmarks->interval_us; 1191 scheme->wmarks.high = sysfs_wmarks->high; 1192 scheme->wmarks.mid = sysfs_wmarks->mid; 1193 scheme->wmarks.low = sysfs_wmarks->low; 1194 } 1195 1196 int damon_sysfs_set_schemes(struct damon_ctx *ctx, 1197 struct damon_sysfs_schemes *sysfs_schemes) 1198 { 1199 struct damos *scheme, *next; 1200 int i = 0; 1201 1202 damon_for_each_scheme_safe(scheme, next, ctx) { 1203 if (i < sysfs_schemes->nr) 1204 damon_sysfs_update_scheme(scheme, 1205 sysfs_schemes->schemes_arr[i]); 1206 else 1207 damon_destroy_scheme(scheme); 1208 i++; 1209 } 1210 1211 for (; i < sysfs_schemes->nr; i++) { 1212 struct damos *scheme, *next; 1213 1214 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]); 1215 if (!scheme) { 1216 damon_for_each_scheme_safe(scheme, next, ctx) 1217 damon_destroy_scheme(scheme); 1218 return -ENOMEM; 1219 } 1220 damon_add_scheme(ctx, scheme); 1221 } 1222 return 0; 1223 } 1224 1225 void damon_sysfs_schemes_update_stats( 1226 struct damon_sysfs_schemes *sysfs_schemes, 1227 struct damon_ctx *ctx) 1228 { 1229 struct damos *scheme; 1230 int schemes_idx = 0; 1231 1232 damon_for_each_scheme(scheme, ctx) { 1233 struct damon_sysfs_stats *sysfs_stats; 1234 1235 /* user could have removed the scheme sysfs dir */ 1236 if (schemes_idx >= sysfs_schemes->nr) 1237 break; 1238 1239 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats; 1240 sysfs_stats->nr_tried = scheme->stat.nr_tried; 1241 sysfs_stats->sz_tried = scheme->stat.sz_tried; 1242 sysfs_stats->nr_applied = scheme->stat.nr_applied; 1243 sysfs_stats->sz_applied = scheme->stat.sz_applied; 1244 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds; 1245 } 1246 } 1247 1248 /* 1249 * damon_sysfs_schemes that need to update its schemes regions dir. Protected 1250 * by damon_sysfs_lock 1251 */ 1252 static struct damon_sysfs_schemes *damon_sysfs_schemes_for_damos_callback; 1253 static int damon_sysfs_schemes_region_idx; 1254 1255 /* 1256 * DAMON callback that called before damos apply. While this callback is 1257 * registered, damon_sysfs_lock should be held to ensure the regions 1258 * directories exist. 1259 */ 1260 static int damon_sysfs_before_damos_apply(struct damon_ctx *ctx, 1261 struct damon_target *t, struct damon_region *r, 1262 struct damos *s) 1263 { 1264 struct damos *scheme; 1265 struct damon_sysfs_scheme_regions *sysfs_regions; 1266 struct damon_sysfs_scheme_region *region; 1267 struct damon_sysfs_schemes *sysfs_schemes = 1268 damon_sysfs_schemes_for_damos_callback; 1269 int schemes_idx = 0; 1270 1271 damon_for_each_scheme(scheme, ctx) { 1272 if (scheme == s) 1273 break; 1274 schemes_idx++; 1275 } 1276 1277 /* user could have removed the scheme sysfs dir */ 1278 if (schemes_idx >= sysfs_schemes->nr) 1279 return 0; 1280 1281 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions; 1282 region = damon_sysfs_scheme_region_alloc(r); 1283 list_add_tail(®ion->list, &sysfs_regions->regions_list); 1284 sysfs_regions->nr_regions++; 1285 if (kobject_init_and_add(®ion->kobj, 1286 &damon_sysfs_scheme_region_ktype, 1287 &sysfs_regions->kobj, "%d", 1288 damon_sysfs_schemes_region_idx++)) { 1289 kobject_put(®ion->kobj); 1290 } 1291 return 0; 1292 } 1293 1294 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */ 1295 int damon_sysfs_schemes_clear_regions( 1296 struct damon_sysfs_schemes *sysfs_schemes, 1297 struct damon_ctx *ctx) 1298 { 1299 struct damos *scheme; 1300 int schemes_idx = 0; 1301 1302 damon_for_each_scheme(scheme, ctx) { 1303 struct damon_sysfs_scheme *sysfs_scheme; 1304 1305 /* user could have removed the scheme sysfs dir */ 1306 if (schemes_idx >= sysfs_schemes->nr) 1307 break; 1308 1309 sysfs_scheme = sysfs_schemes->schemes_arr[schemes_idx++]; 1310 damon_sysfs_scheme_regions_rm_dirs( 1311 sysfs_scheme->tried_regions); 1312 } 1313 return 0; 1314 } 1315 1316 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */ 1317 int damon_sysfs_schemes_update_regions_start( 1318 struct damon_sysfs_schemes *sysfs_schemes, 1319 struct damon_ctx *ctx) 1320 { 1321 damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx); 1322 damon_sysfs_schemes_for_damos_callback = sysfs_schemes; 1323 ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply; 1324 return 0; 1325 } 1326 1327 /* 1328 * Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock. Caller 1329 * should unlock damon_sysfs_lock which held before 1330 * damon_sysfs_schemes_update_regions_start() 1331 */ 1332 int damon_sysfs_schemes_update_regions_stop(struct damon_ctx *ctx) 1333 { 1334 damon_sysfs_schemes_for_damos_callback = NULL; 1335 ctx->callback.before_damos_apply = NULL; 1336 damon_sysfs_schemes_region_idx = 0; 1337 return 0; 1338 } 1339