1 // SPDX-License-Identifier: GPL-2.0
3 * DAMON sysfs Interface
5 * Copyright (c) 2022 SeongJae Park <sj@kernel.org>
8 #include <linux/slab.h>
10 #include "sysfs-common.h"
13 * scheme region directory
16 struct damon_sysfs_scheme_region {
18 struct damon_addr_range ar;
19 unsigned int nr_accesses;
21 struct list_head list;
24 static struct damon_sysfs_scheme_region *damon_sysfs_scheme_region_alloc(
25 struct damon_region *region)
27 struct damon_sysfs_scheme_region *sysfs_region = kmalloc(
28 sizeof(*sysfs_region), GFP_KERNEL);
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);
40 static ssize_t start_show(struct kobject *kobj, struct kobj_attribute *attr,
43 struct damon_sysfs_scheme_region *region = container_of(kobj,
44 struct damon_sysfs_scheme_region, kobj);
46 return sysfs_emit(buf, "%lu\n", region->ar.start);
49 static ssize_t end_show(struct kobject *kobj, struct kobj_attribute *attr,
52 struct damon_sysfs_scheme_region *region = container_of(kobj,
53 struct damon_sysfs_scheme_region, kobj);
55 return sysfs_emit(buf, "%lu\n", region->ar.end);
58 static ssize_t nr_accesses_show(struct kobject *kobj,
59 struct kobj_attribute *attr, char *buf)
61 struct damon_sysfs_scheme_region *region = container_of(kobj,
62 struct damon_sysfs_scheme_region, kobj);
64 return sysfs_emit(buf, "%u\n", region->nr_accesses);
67 static ssize_t age_show(struct kobject *kobj, struct kobj_attribute *attr,
70 struct damon_sysfs_scheme_region *region = container_of(kobj,
71 struct damon_sysfs_scheme_region, kobj);
73 return sysfs_emit(buf, "%u\n", region->age);
76 static void damon_sysfs_scheme_region_release(struct kobject *kobj)
78 struct damon_sysfs_scheme_region *region = container_of(kobj,
79 struct damon_sysfs_scheme_region, kobj);
81 list_del(®ion->list);
85 static struct kobj_attribute damon_sysfs_scheme_region_start_attr =
86 __ATTR_RO_MODE(start, 0400);
88 static struct kobj_attribute damon_sysfs_scheme_region_end_attr =
89 __ATTR_RO_MODE(end, 0400);
91 static struct kobj_attribute damon_sysfs_scheme_region_nr_accesses_attr =
92 __ATTR_RO_MODE(nr_accesses, 0400);
94 static struct kobj_attribute damon_sysfs_scheme_region_age_attr =
95 __ATTR_RO_MODE(age, 0400);
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,
104 ATTRIBUTE_GROUPS(damon_sysfs_scheme_region);
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,
113 * scheme regions directory
116 struct damon_sysfs_scheme_regions {
118 struct list_head regions_list;
122 static struct damon_sysfs_scheme_regions *
123 damon_sysfs_scheme_regions_alloc(void)
125 struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions),
128 regions->kobj = (struct kobject){};
129 INIT_LIST_HEAD(®ions->regions_list);
130 regions->nr_regions = 0;
134 static void damon_sysfs_scheme_regions_rm_dirs(
135 struct damon_sysfs_scheme_regions *regions)
137 struct damon_sysfs_scheme_region *r, *next;
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--;
146 static void damon_sysfs_scheme_regions_release(struct kobject *kobj)
148 kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj));
151 static struct attribute *damon_sysfs_scheme_regions_attrs[] = {
154 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions);
156 static const 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,
163 * schemes/stats directory
166 struct damon_sysfs_stats {
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;
175 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void)
177 return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL);
180 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
183 struct damon_sysfs_stats *stats = container_of(kobj,
184 struct damon_sysfs_stats, kobj);
186 return sysfs_emit(buf, "%lu\n", stats->nr_tried);
189 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
192 struct damon_sysfs_stats *stats = container_of(kobj,
193 struct damon_sysfs_stats, kobj);
195 return sysfs_emit(buf, "%lu\n", stats->sz_tried);
198 static ssize_t nr_applied_show(struct kobject *kobj,
199 struct kobj_attribute *attr, char *buf)
201 struct damon_sysfs_stats *stats = container_of(kobj,
202 struct damon_sysfs_stats, kobj);
204 return sysfs_emit(buf, "%lu\n", stats->nr_applied);
207 static ssize_t sz_applied_show(struct kobject *kobj,
208 struct kobj_attribute *attr, char *buf)
210 struct damon_sysfs_stats *stats = container_of(kobj,
211 struct damon_sysfs_stats, kobj);
213 return sysfs_emit(buf, "%lu\n", stats->sz_applied);
216 static ssize_t qt_exceeds_show(struct kobject *kobj,
217 struct kobj_attribute *attr, char *buf)
219 struct damon_sysfs_stats *stats = container_of(kobj,
220 struct damon_sysfs_stats, kobj);
222 return sysfs_emit(buf, "%lu\n", stats->qt_exceeds);
225 static void damon_sysfs_stats_release(struct kobject *kobj)
227 kfree(container_of(kobj, struct damon_sysfs_stats, kobj));
230 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr =
231 __ATTR_RO_MODE(nr_tried, 0400);
233 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr =
234 __ATTR_RO_MODE(sz_tried, 0400);
236 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr =
237 __ATTR_RO_MODE(nr_applied, 0400);
239 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr =
240 __ATTR_RO_MODE(sz_applied, 0400);
242 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr =
243 __ATTR_RO_MODE(qt_exceeds, 0400);
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,
253 ATTRIBUTE_GROUPS(damon_sysfs_stats);
255 static const 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,
265 struct damon_sysfs_scheme_filter {
267 enum damos_filter_type type;
272 static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc(void)
274 return kzalloc(sizeof(struct damon_sysfs_scheme_filter), GFP_KERNEL);
277 /* Should match with enum damos_filter_type */
278 static const char * const damon_sysfs_scheme_filter_type_strs[] = {
283 static ssize_t type_show(struct kobject *kobj,
284 struct kobj_attribute *attr, char *buf)
286 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
287 struct damon_sysfs_scheme_filter, kobj);
289 return sysfs_emit(buf, "%s\n",
290 damon_sysfs_scheme_filter_type_strs[filter->type]);
293 static ssize_t type_store(struct kobject *kobj,
294 struct kobj_attribute *attr, const char *buf, size_t count)
296 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
297 struct damon_sysfs_scheme_filter, kobj);
298 enum damos_filter_type type;
299 ssize_t ret = -EINVAL;
301 for (type = 0; type < NR_DAMOS_FILTER_TYPES; type++) {
302 if (sysfs_streq(buf, damon_sysfs_scheme_filter_type_strs[
312 static ssize_t matching_show(struct kobject *kobj,
313 struct kobj_attribute *attr, char *buf)
315 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
316 struct damon_sysfs_scheme_filter, kobj);
318 return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N');
321 static ssize_t matching_store(struct kobject *kobj,
322 struct kobj_attribute *attr, const char *buf, size_t count)
324 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
325 struct damon_sysfs_scheme_filter, kobj);
327 int err = kstrtobool(buf, &matching);
332 filter->matching = matching;
336 static ssize_t memcg_path_show(struct kobject *kobj,
337 struct kobj_attribute *attr, char *buf)
339 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
340 struct damon_sysfs_scheme_filter, kobj);
342 return sysfs_emit(buf, "%s\n",
343 filter->memcg_path ? filter->memcg_path : "");
346 static ssize_t memcg_path_store(struct kobject *kobj,
347 struct kobj_attribute *attr, const char *buf, size_t count)
349 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
350 struct damon_sysfs_scheme_filter, kobj);
351 char *path = kmalloc(sizeof(*path) * (count + 1), GFP_KERNEL);
356 strscpy(path, buf, count + 1);
357 filter->memcg_path = path;
361 static void damon_sysfs_scheme_filter_release(struct kobject *kobj)
363 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
364 struct damon_sysfs_scheme_filter, kobj);
366 kfree(filter->memcg_path);
370 static struct kobj_attribute damon_sysfs_scheme_filter_type_attr =
371 __ATTR_RW_MODE(type, 0600);
373 static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr =
374 __ATTR_RW_MODE(matching, 0600);
376 static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr =
377 __ATTR_RW_MODE(memcg_path, 0600);
379 static struct attribute *damon_sysfs_scheme_filter_attrs[] = {
380 &damon_sysfs_scheme_filter_type_attr.attr,
381 &damon_sysfs_scheme_filter_matching_attr.attr,
382 &damon_sysfs_scheme_filter_memcg_path_attr.attr,
385 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter);
387 static const struct kobj_type damon_sysfs_scheme_filter_ktype = {
388 .release = damon_sysfs_scheme_filter_release,
389 .sysfs_ops = &kobj_sysfs_ops,
390 .default_groups = damon_sysfs_scheme_filter_groups,
397 struct damon_sysfs_scheme_filters {
399 struct damon_sysfs_scheme_filter **filters_arr;
403 static struct damon_sysfs_scheme_filters *
404 damon_sysfs_scheme_filters_alloc(void)
406 return kzalloc(sizeof(struct damon_sysfs_scheme_filters), GFP_KERNEL);
409 static void damon_sysfs_scheme_filters_rm_dirs(
410 struct damon_sysfs_scheme_filters *filters)
412 struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr;
415 for (i = 0; i < filters->nr; i++)
416 kobject_put(&filters_arr[i]->kobj);
419 filters->filters_arr = NULL;
422 static int damon_sysfs_scheme_filters_add_dirs(
423 struct damon_sysfs_scheme_filters *filters, int nr_filters)
425 struct damon_sysfs_scheme_filter **filters_arr, *filter;
428 damon_sysfs_scheme_filters_rm_dirs(filters);
432 filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr),
433 GFP_KERNEL | __GFP_NOWARN);
436 filters->filters_arr = filters_arr;
438 for (i = 0; i < nr_filters; i++) {
439 filter = damon_sysfs_scheme_filter_alloc();
441 damon_sysfs_scheme_filters_rm_dirs(filters);
445 err = kobject_init_and_add(&filter->kobj,
446 &damon_sysfs_scheme_filter_ktype,
447 &filters->kobj, "%d", i);
449 kobject_put(&filter->kobj);
450 damon_sysfs_scheme_filters_rm_dirs(filters);
454 filters_arr[i] = filter;
460 static ssize_t nr_filters_show(struct kobject *kobj,
461 struct kobj_attribute *attr, char *buf)
463 struct damon_sysfs_scheme_filters *filters = container_of(kobj,
464 struct damon_sysfs_scheme_filters, kobj);
466 return sysfs_emit(buf, "%d\n", filters->nr);
469 static ssize_t nr_filters_store(struct kobject *kobj,
470 struct kobj_attribute *attr, const char *buf, size_t count)
472 struct damon_sysfs_scheme_filters *filters;
473 int nr, err = kstrtoint(buf, 0, &nr);
480 filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj);
482 if (!mutex_trylock(&damon_sysfs_lock))
484 err = damon_sysfs_scheme_filters_add_dirs(filters, nr);
485 mutex_unlock(&damon_sysfs_lock);
492 static void damon_sysfs_scheme_filters_release(struct kobject *kobj)
494 kfree(container_of(kobj, struct damon_sysfs_scheme_filters, kobj));
497 static struct kobj_attribute damon_sysfs_scheme_filters_nr_attr =
498 __ATTR_RW_MODE(nr_filters, 0600);
500 static struct attribute *damon_sysfs_scheme_filters_attrs[] = {
501 &damon_sysfs_scheme_filters_nr_attr.attr,
504 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filters);
506 static const struct kobj_type damon_sysfs_scheme_filters_ktype = {
507 .release = damon_sysfs_scheme_filters_release,
508 .sysfs_ops = &kobj_sysfs_ops,
509 .default_groups = damon_sysfs_scheme_filters_groups,
513 * watermarks directory
516 struct damon_sysfs_watermarks {
518 enum damos_wmark_metric metric;
519 unsigned long interval_us;
525 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
526 enum damos_wmark_metric metric, unsigned long interval_us,
527 unsigned long high, unsigned long mid, unsigned long low)
529 struct damon_sysfs_watermarks *watermarks = kmalloc(
530 sizeof(*watermarks), GFP_KERNEL);
534 watermarks->kobj = (struct kobject){};
535 watermarks->metric = metric;
536 watermarks->interval_us = interval_us;
537 watermarks->high = high;
538 watermarks->mid = mid;
539 watermarks->low = low;
543 /* Should match with enum damos_wmark_metric */
544 static const char * const damon_sysfs_wmark_metric_strs[] = {
549 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
552 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
553 struct damon_sysfs_watermarks, kobj);
555 return sysfs_emit(buf, "%s\n",
556 damon_sysfs_wmark_metric_strs[watermarks->metric]);
559 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
560 const char *buf, size_t count)
562 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
563 struct damon_sysfs_watermarks, kobj);
564 enum damos_wmark_metric metric;
566 for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) {
567 if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) {
568 watermarks->metric = metric;
575 static ssize_t interval_us_show(struct kobject *kobj,
576 struct kobj_attribute *attr, char *buf)
578 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
579 struct damon_sysfs_watermarks, kobj);
581 return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
584 static ssize_t interval_us_store(struct kobject *kobj,
585 struct kobj_attribute *attr, const char *buf, size_t count)
587 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
588 struct damon_sysfs_watermarks, kobj);
589 int err = kstrtoul(buf, 0, &watermarks->interval_us);
591 return err ? err : count;
594 static ssize_t high_show(struct kobject *kobj,
595 struct kobj_attribute *attr, char *buf)
597 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
598 struct damon_sysfs_watermarks, kobj);
600 return sysfs_emit(buf, "%lu\n", watermarks->high);
603 static ssize_t high_store(struct kobject *kobj,
604 struct kobj_attribute *attr, const char *buf, size_t count)
606 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
607 struct damon_sysfs_watermarks, kobj);
608 int err = kstrtoul(buf, 0, &watermarks->high);
610 return err ? err : count;
613 static ssize_t mid_show(struct kobject *kobj,
614 struct kobj_attribute *attr, char *buf)
616 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
617 struct damon_sysfs_watermarks, kobj);
619 return sysfs_emit(buf, "%lu\n", watermarks->mid);
622 static ssize_t mid_store(struct kobject *kobj,
623 struct kobj_attribute *attr, const char *buf, size_t count)
625 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
626 struct damon_sysfs_watermarks, kobj);
627 int err = kstrtoul(buf, 0, &watermarks->mid);
629 return err ? err : count;
632 static ssize_t low_show(struct kobject *kobj,
633 struct kobj_attribute *attr, char *buf)
635 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
636 struct damon_sysfs_watermarks, kobj);
638 return sysfs_emit(buf, "%lu\n", watermarks->low);
641 static ssize_t low_store(struct kobject *kobj,
642 struct kobj_attribute *attr, const char *buf, size_t count)
644 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
645 struct damon_sysfs_watermarks, kobj);
646 int err = kstrtoul(buf, 0, &watermarks->low);
648 return err ? err : count;
651 static void damon_sysfs_watermarks_release(struct kobject *kobj)
653 kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
656 static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
657 __ATTR_RW_MODE(metric, 0600);
659 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
660 __ATTR_RW_MODE(interval_us, 0600);
662 static struct kobj_attribute damon_sysfs_watermarks_high_attr =
663 __ATTR_RW_MODE(high, 0600);
665 static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
666 __ATTR_RW_MODE(mid, 0600);
668 static struct kobj_attribute damon_sysfs_watermarks_low_attr =
669 __ATTR_RW_MODE(low, 0600);
671 static struct attribute *damon_sysfs_watermarks_attrs[] = {
672 &damon_sysfs_watermarks_metric_attr.attr,
673 &damon_sysfs_watermarks_interval_us_attr.attr,
674 &damon_sysfs_watermarks_high_attr.attr,
675 &damon_sysfs_watermarks_mid_attr.attr,
676 &damon_sysfs_watermarks_low_attr.attr,
679 ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
681 static const struct kobj_type damon_sysfs_watermarks_ktype = {
682 .release = damon_sysfs_watermarks_release,
683 .sysfs_ops = &kobj_sysfs_ops,
684 .default_groups = damon_sysfs_watermarks_groups,
688 * scheme/weights directory
691 struct damon_sysfs_weights {
694 unsigned int nr_accesses;
698 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
699 unsigned int nr_accesses, unsigned int age)
701 struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
706 weights->kobj = (struct kobject){};
708 weights->nr_accesses = nr_accesses;
713 static ssize_t sz_permil_show(struct kobject *kobj,
714 struct kobj_attribute *attr, char *buf)
716 struct damon_sysfs_weights *weights = container_of(kobj,
717 struct damon_sysfs_weights, kobj);
719 return sysfs_emit(buf, "%u\n", weights->sz);
722 static ssize_t sz_permil_store(struct kobject *kobj,
723 struct kobj_attribute *attr, const char *buf, size_t count)
725 struct damon_sysfs_weights *weights = container_of(kobj,
726 struct damon_sysfs_weights, kobj);
727 int err = kstrtouint(buf, 0, &weights->sz);
729 return err ? err : count;
732 static ssize_t nr_accesses_permil_show(struct kobject *kobj,
733 struct kobj_attribute *attr, char *buf)
735 struct damon_sysfs_weights *weights = container_of(kobj,
736 struct damon_sysfs_weights, kobj);
738 return sysfs_emit(buf, "%u\n", weights->nr_accesses);
741 static ssize_t nr_accesses_permil_store(struct kobject *kobj,
742 struct kobj_attribute *attr, const char *buf, size_t count)
744 struct damon_sysfs_weights *weights = container_of(kobj,
745 struct damon_sysfs_weights, kobj);
746 int err = kstrtouint(buf, 0, &weights->nr_accesses);
748 return err ? err : count;
751 static ssize_t age_permil_show(struct kobject *kobj,
752 struct kobj_attribute *attr, char *buf)
754 struct damon_sysfs_weights *weights = container_of(kobj,
755 struct damon_sysfs_weights, kobj);
757 return sysfs_emit(buf, "%u\n", weights->age);
760 static ssize_t age_permil_store(struct kobject *kobj,
761 struct kobj_attribute *attr, const char *buf, size_t count)
763 struct damon_sysfs_weights *weights = container_of(kobj,
764 struct damon_sysfs_weights, kobj);
765 int err = kstrtouint(buf, 0, &weights->age);
767 return err ? err : count;
770 static void damon_sysfs_weights_release(struct kobject *kobj)
772 kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
775 static struct kobj_attribute damon_sysfs_weights_sz_attr =
776 __ATTR_RW_MODE(sz_permil, 0600);
778 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
779 __ATTR_RW_MODE(nr_accesses_permil, 0600);
781 static struct kobj_attribute damon_sysfs_weights_age_attr =
782 __ATTR_RW_MODE(age_permil, 0600);
784 static struct attribute *damon_sysfs_weights_attrs[] = {
785 &damon_sysfs_weights_sz_attr.attr,
786 &damon_sysfs_weights_nr_accesses_attr.attr,
787 &damon_sysfs_weights_age_attr.attr,
790 ATTRIBUTE_GROUPS(damon_sysfs_weights);
792 static const struct kobj_type damon_sysfs_weights_ktype = {
793 .release = damon_sysfs_weights_release,
794 .sysfs_ops = &kobj_sysfs_ops,
795 .default_groups = damon_sysfs_weights_groups,
802 struct damon_sysfs_quotas {
804 struct damon_sysfs_weights *weights;
807 unsigned long reset_interval_ms;
810 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
812 return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
815 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
817 struct damon_sysfs_weights *weights;
820 weights = damon_sysfs_weights_alloc(0, 0, 0);
824 err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
825 "as->kobj, "weights");
827 kobject_put(&weights->kobj);
829 quotas->weights = weights;
833 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
835 kobject_put("as->weights->kobj);
838 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
841 struct damon_sysfs_quotas *quotas = container_of(kobj,
842 struct damon_sysfs_quotas, kobj);
844 return sysfs_emit(buf, "%lu\n", quotas->ms);
847 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
848 const char *buf, size_t count)
850 struct damon_sysfs_quotas *quotas = container_of(kobj,
851 struct damon_sysfs_quotas, kobj);
852 int err = kstrtoul(buf, 0, "as->ms);
859 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
862 struct damon_sysfs_quotas *quotas = container_of(kobj,
863 struct damon_sysfs_quotas, kobj);
865 return sysfs_emit(buf, "%lu\n", quotas->sz);
868 static ssize_t bytes_store(struct kobject *kobj,
869 struct kobj_attribute *attr, const char *buf, size_t count)
871 struct damon_sysfs_quotas *quotas = container_of(kobj,
872 struct damon_sysfs_quotas, kobj);
873 int err = kstrtoul(buf, 0, "as->sz);
880 static ssize_t reset_interval_ms_show(struct kobject *kobj,
881 struct kobj_attribute *attr, char *buf)
883 struct damon_sysfs_quotas *quotas = container_of(kobj,
884 struct damon_sysfs_quotas, kobj);
886 return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
889 static ssize_t reset_interval_ms_store(struct kobject *kobj,
890 struct kobj_attribute *attr, const char *buf, size_t count)
892 struct damon_sysfs_quotas *quotas = container_of(kobj,
893 struct damon_sysfs_quotas, kobj);
894 int err = kstrtoul(buf, 0, "as->reset_interval_ms);
901 static void damon_sysfs_quotas_release(struct kobject *kobj)
903 kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
906 static struct kobj_attribute damon_sysfs_quotas_ms_attr =
907 __ATTR_RW_MODE(ms, 0600);
909 static struct kobj_attribute damon_sysfs_quotas_sz_attr =
910 __ATTR_RW_MODE(bytes, 0600);
912 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
913 __ATTR_RW_MODE(reset_interval_ms, 0600);
915 static struct attribute *damon_sysfs_quotas_attrs[] = {
916 &damon_sysfs_quotas_ms_attr.attr,
917 &damon_sysfs_quotas_sz_attr.attr,
918 &damon_sysfs_quotas_reset_interval_ms_attr.attr,
921 ATTRIBUTE_GROUPS(damon_sysfs_quotas);
923 static const struct kobj_type damon_sysfs_quotas_ktype = {
924 .release = damon_sysfs_quotas_release,
925 .sysfs_ops = &kobj_sysfs_ops,
926 .default_groups = damon_sysfs_quotas_groups,
930 * access_pattern directory
933 struct damon_sysfs_access_pattern {
935 struct damon_sysfs_ul_range *sz;
936 struct damon_sysfs_ul_range *nr_accesses;
937 struct damon_sysfs_ul_range *age;
941 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void)
943 struct damon_sysfs_access_pattern *access_pattern =
944 kmalloc(sizeof(*access_pattern), GFP_KERNEL);
948 access_pattern->kobj = (struct kobject){};
949 return access_pattern;
952 static int damon_sysfs_access_pattern_add_range_dir(
953 struct damon_sysfs_access_pattern *access_pattern,
954 struct damon_sysfs_ul_range **range_dir_ptr,
957 struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0);
962 err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype,
963 &access_pattern->kobj, name);
965 kobject_put(&range->kobj);
967 *range_dir_ptr = range;
971 static int damon_sysfs_access_pattern_add_dirs(
972 struct damon_sysfs_access_pattern *access_pattern)
976 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
977 &access_pattern->sz, "sz");
981 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
982 &access_pattern->nr_accesses, "nr_accesses");
984 goto put_nr_accesses_sz_out;
986 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
987 &access_pattern->age, "age");
989 goto put_age_nr_accesses_sz_out;
992 put_age_nr_accesses_sz_out:
993 kobject_put(&access_pattern->age->kobj);
994 access_pattern->age = NULL;
995 put_nr_accesses_sz_out:
996 kobject_put(&access_pattern->nr_accesses->kobj);
997 access_pattern->nr_accesses = NULL;
999 kobject_put(&access_pattern->sz->kobj);
1000 access_pattern->sz = NULL;
1004 static void damon_sysfs_access_pattern_rm_dirs(
1005 struct damon_sysfs_access_pattern *access_pattern)
1007 kobject_put(&access_pattern->sz->kobj);
1008 kobject_put(&access_pattern->nr_accesses->kobj);
1009 kobject_put(&access_pattern->age->kobj);
1012 static void damon_sysfs_access_pattern_release(struct kobject *kobj)
1014 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj));
1017 static struct attribute *damon_sysfs_access_pattern_attrs[] = {
1020 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern);
1022 static const struct kobj_type damon_sysfs_access_pattern_ktype = {
1023 .release = damon_sysfs_access_pattern_release,
1024 .sysfs_ops = &kobj_sysfs_ops,
1025 .default_groups = damon_sysfs_access_pattern_groups,
1032 struct damon_sysfs_scheme {
1033 struct kobject kobj;
1034 enum damos_action action;
1035 struct damon_sysfs_access_pattern *access_pattern;
1036 struct damon_sysfs_quotas *quotas;
1037 struct damon_sysfs_watermarks *watermarks;
1038 struct damon_sysfs_scheme_filters *filters;
1039 struct damon_sysfs_stats *stats;
1040 struct damon_sysfs_scheme_regions *tried_regions;
1043 /* This should match with enum damos_action */
1044 static const char * const damon_sysfs_damos_action_strs[] = {
1055 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
1056 enum damos_action action)
1058 struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme),
1063 scheme->kobj = (struct kobject){};
1064 scheme->action = action;
1068 static int damon_sysfs_scheme_set_access_pattern(
1069 struct damon_sysfs_scheme *scheme)
1071 struct damon_sysfs_access_pattern *access_pattern;
1074 access_pattern = damon_sysfs_access_pattern_alloc();
1075 if (!access_pattern)
1077 err = kobject_init_and_add(&access_pattern->kobj,
1078 &damon_sysfs_access_pattern_ktype, &scheme->kobj,
1082 err = damon_sysfs_access_pattern_add_dirs(access_pattern);
1085 scheme->access_pattern = access_pattern;
1089 kobject_put(&access_pattern->kobj);
1093 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
1095 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
1100 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype,
1101 &scheme->kobj, "quotas");
1104 err = damon_sysfs_quotas_add_dirs(quotas);
1107 scheme->quotas = quotas;
1111 kobject_put("as->kobj);
1115 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
1117 struct damon_sysfs_watermarks *watermarks =
1118 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
1123 err = kobject_init_and_add(&watermarks->kobj,
1124 &damon_sysfs_watermarks_ktype, &scheme->kobj,
1127 kobject_put(&watermarks->kobj);
1129 scheme->watermarks = watermarks;
1133 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme)
1135 struct damon_sysfs_scheme_filters *filters =
1136 damon_sysfs_scheme_filters_alloc();
1141 err = kobject_init_and_add(&filters->kobj,
1142 &damon_sysfs_scheme_filters_ktype, &scheme->kobj,
1145 kobject_put(&filters->kobj);
1147 scheme->filters = filters;
1151 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme)
1153 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc();
1158 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype,
1159 &scheme->kobj, "stats");
1161 kobject_put(&stats->kobj);
1163 scheme->stats = stats;
1167 static int damon_sysfs_scheme_set_tried_regions(
1168 struct damon_sysfs_scheme *scheme)
1170 struct damon_sysfs_scheme_regions *tried_regions =
1171 damon_sysfs_scheme_regions_alloc();
1176 err = kobject_init_and_add(&tried_regions->kobj,
1177 &damon_sysfs_scheme_regions_ktype, &scheme->kobj,
1180 kobject_put(&tried_regions->kobj);
1182 scheme->tried_regions = tried_regions;
1186 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
1190 err = damon_sysfs_scheme_set_access_pattern(scheme);
1193 err = damon_sysfs_scheme_set_quotas(scheme);
1195 goto put_access_pattern_out;
1196 err = damon_sysfs_scheme_set_watermarks(scheme);
1198 goto put_quotas_access_pattern_out;
1199 err = damon_sysfs_scheme_set_filters(scheme);
1201 goto put_watermarks_quotas_access_pattern_out;
1202 err = damon_sysfs_scheme_set_stats(scheme);
1204 goto put_filters_watermarks_quotas_access_pattern_out;
1205 err = damon_sysfs_scheme_set_tried_regions(scheme);
1207 goto put_tried_regions_out;
1210 put_tried_regions_out:
1211 kobject_put(&scheme->tried_regions->kobj);
1212 scheme->tried_regions = NULL;
1213 put_filters_watermarks_quotas_access_pattern_out:
1214 kobject_put(&scheme->filters->kobj);
1215 scheme->filters = NULL;
1216 put_watermarks_quotas_access_pattern_out:
1217 kobject_put(&scheme->watermarks->kobj);
1218 scheme->watermarks = NULL;
1219 put_quotas_access_pattern_out:
1220 kobject_put(&scheme->quotas->kobj);
1221 scheme->quotas = NULL;
1222 put_access_pattern_out:
1223 kobject_put(&scheme->access_pattern->kobj);
1224 scheme->access_pattern = NULL;
1228 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
1230 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
1231 kobject_put(&scheme->access_pattern->kobj);
1232 damon_sysfs_quotas_rm_dirs(scheme->quotas);
1233 kobject_put(&scheme->quotas->kobj);
1234 kobject_put(&scheme->watermarks->kobj);
1235 damon_sysfs_scheme_filters_rm_dirs(scheme->filters);
1236 kobject_put(&scheme->filters->kobj);
1237 kobject_put(&scheme->stats->kobj);
1238 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions);
1239 kobject_put(&scheme->tried_regions->kobj);
1242 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
1245 struct damon_sysfs_scheme *scheme = container_of(kobj,
1246 struct damon_sysfs_scheme, kobj);
1248 return sysfs_emit(buf, "%s\n",
1249 damon_sysfs_damos_action_strs[scheme->action]);
1252 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr,
1253 const char *buf, size_t count)
1255 struct damon_sysfs_scheme *scheme = container_of(kobj,
1256 struct damon_sysfs_scheme, kobj);
1257 enum damos_action action;
1259 for (action = 0; action < NR_DAMOS_ACTIONS; action++) {
1260 if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) {
1261 scheme->action = action;
1268 static void damon_sysfs_scheme_release(struct kobject *kobj)
1270 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
1273 static struct kobj_attribute damon_sysfs_scheme_action_attr =
1274 __ATTR_RW_MODE(action, 0600);
1276 static struct attribute *damon_sysfs_scheme_attrs[] = {
1277 &damon_sysfs_scheme_action_attr.attr,
1280 ATTRIBUTE_GROUPS(damon_sysfs_scheme);
1282 static const struct kobj_type damon_sysfs_scheme_ktype = {
1283 .release = damon_sysfs_scheme_release,
1284 .sysfs_ops = &kobj_sysfs_ops,
1285 .default_groups = damon_sysfs_scheme_groups,
1292 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void)
1294 return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL);
1297 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes)
1299 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr;
1302 for (i = 0; i < schemes->nr; i++) {
1303 damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
1304 kobject_put(&schemes_arr[i]->kobj);
1308 schemes->schemes_arr = NULL;
1311 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes,
1314 struct damon_sysfs_scheme **schemes_arr, *scheme;
1317 damon_sysfs_schemes_rm_dirs(schemes);
1321 schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr),
1322 GFP_KERNEL | __GFP_NOWARN);
1325 schemes->schemes_arr = schemes_arr;
1327 for (i = 0; i < nr_schemes; i++) {
1328 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT);
1330 damon_sysfs_schemes_rm_dirs(schemes);
1334 err = kobject_init_and_add(&scheme->kobj,
1335 &damon_sysfs_scheme_ktype, &schemes->kobj,
1339 err = damon_sysfs_scheme_add_dirs(scheme);
1343 schemes_arr[i] = scheme;
1349 damon_sysfs_schemes_rm_dirs(schemes);
1350 kobject_put(&scheme->kobj);
1354 static ssize_t nr_schemes_show(struct kobject *kobj,
1355 struct kobj_attribute *attr, char *buf)
1357 struct damon_sysfs_schemes *schemes = container_of(kobj,
1358 struct damon_sysfs_schemes, kobj);
1360 return sysfs_emit(buf, "%d\n", schemes->nr);
1363 static ssize_t nr_schemes_store(struct kobject *kobj,
1364 struct kobj_attribute *attr, const char *buf, size_t count)
1366 struct damon_sysfs_schemes *schemes;
1367 int nr, err = kstrtoint(buf, 0, &nr);
1374 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj);
1376 if (!mutex_trylock(&damon_sysfs_lock))
1378 err = damon_sysfs_schemes_add_dirs(schemes, nr);
1379 mutex_unlock(&damon_sysfs_lock);
1385 static void damon_sysfs_schemes_release(struct kobject *kobj)
1387 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj));
1390 static struct kobj_attribute damon_sysfs_schemes_nr_attr =
1391 __ATTR_RW_MODE(nr_schemes, 0600);
1393 static struct attribute *damon_sysfs_schemes_attrs[] = {
1394 &damon_sysfs_schemes_nr_attr.attr,
1397 ATTRIBUTE_GROUPS(damon_sysfs_schemes);
1399 const struct kobj_type damon_sysfs_schemes_ktype = {
1400 .release = damon_sysfs_schemes_release,
1401 .sysfs_ops = &kobj_sysfs_ops,
1402 .default_groups = damon_sysfs_schemes_groups,
1405 static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg,
1406 char *memcg_path_buf, char *path)
1409 cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX);
1410 if (sysfs_streq(memcg_path_buf, path))
1412 #endif /* CONFIG_MEMCG */
1416 static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id)
1418 struct mem_cgroup *memcg;
1425 path = kmalloc(sizeof(*path) * PATH_MAX, GFP_KERNEL);
1429 for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg;
1430 memcg = mem_cgroup_iter(NULL, memcg, NULL)) {
1431 /* skip removed memcg */
1432 if (!mem_cgroup_id(memcg))
1434 if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) {
1435 *id = mem_cgroup_id(memcg);
1442 return found ? 0 : -EINVAL;
1445 static int damon_sysfs_set_scheme_filters(struct damos *scheme,
1446 struct damon_sysfs_scheme_filters *sysfs_filters)
1449 struct damos_filter *filter, *next;
1451 damos_for_each_filter_safe(filter, next, scheme)
1452 damos_destroy_filter(filter);
1454 for (i = 0; i < sysfs_filters->nr; i++) {
1455 struct damon_sysfs_scheme_filter *sysfs_filter =
1456 sysfs_filters->filters_arr[i];
1457 struct damos_filter *filter =
1458 damos_new_filter(sysfs_filter->type,
1459 sysfs_filter->matching);
1464 if (filter->type == DAMOS_FILTER_TYPE_MEMCG) {
1465 err = damon_sysfs_memcg_path_to_id(
1466 sysfs_filter->memcg_path,
1469 damos_destroy_filter(filter);
1473 damos_add_filter(scheme, filter);
1478 static struct damos *damon_sysfs_mk_scheme(
1479 struct damon_sysfs_scheme *sysfs_scheme)
1481 struct damon_sysfs_access_pattern *access_pattern =
1482 sysfs_scheme->access_pattern;
1483 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1484 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1485 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1486 struct damon_sysfs_scheme_filters *sysfs_filters =
1487 sysfs_scheme->filters;
1488 struct damos *scheme;
1491 struct damos_access_pattern pattern = {
1492 .min_sz_region = access_pattern->sz->min,
1493 .max_sz_region = access_pattern->sz->max,
1494 .min_nr_accesses = access_pattern->nr_accesses->min,
1495 .max_nr_accesses = access_pattern->nr_accesses->max,
1496 .min_age_region = access_pattern->age->min,
1497 .max_age_region = access_pattern->age->max,
1499 struct damos_quota quota = {
1500 .ms = sysfs_quotas->ms,
1501 .sz = sysfs_quotas->sz,
1502 .reset_interval = sysfs_quotas->reset_interval_ms,
1503 .weight_sz = sysfs_weights->sz,
1504 .weight_nr_accesses = sysfs_weights->nr_accesses,
1505 .weight_age = sysfs_weights->age,
1507 struct damos_watermarks wmarks = {
1508 .metric = sysfs_wmarks->metric,
1509 .interval = sysfs_wmarks->interval_us,
1510 .high = sysfs_wmarks->high,
1511 .mid = sysfs_wmarks->mid,
1512 .low = sysfs_wmarks->low,
1515 scheme = damon_new_scheme(&pattern, sysfs_scheme->action, "a,
1520 err = damon_sysfs_set_scheme_filters(scheme, sysfs_filters);
1522 damon_destroy_scheme(scheme);
1528 static void damon_sysfs_update_scheme(struct damos *scheme,
1529 struct damon_sysfs_scheme *sysfs_scheme)
1531 struct damon_sysfs_access_pattern *access_pattern =
1532 sysfs_scheme->access_pattern;
1533 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1534 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1535 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1538 scheme->pattern.min_sz_region = access_pattern->sz->min;
1539 scheme->pattern.max_sz_region = access_pattern->sz->max;
1540 scheme->pattern.min_nr_accesses = access_pattern->nr_accesses->min;
1541 scheme->pattern.max_nr_accesses = access_pattern->nr_accesses->max;
1542 scheme->pattern.min_age_region = access_pattern->age->min;
1543 scheme->pattern.max_age_region = access_pattern->age->max;
1545 scheme->action = sysfs_scheme->action;
1547 scheme->quota.ms = sysfs_quotas->ms;
1548 scheme->quota.sz = sysfs_quotas->sz;
1549 scheme->quota.reset_interval = sysfs_quotas->reset_interval_ms;
1550 scheme->quota.weight_sz = sysfs_weights->sz;
1551 scheme->quota.weight_nr_accesses = sysfs_weights->nr_accesses;
1552 scheme->quota.weight_age = sysfs_weights->age;
1554 scheme->wmarks.metric = sysfs_wmarks->metric;
1555 scheme->wmarks.interval = sysfs_wmarks->interval_us;
1556 scheme->wmarks.high = sysfs_wmarks->high;
1557 scheme->wmarks.mid = sysfs_wmarks->mid;
1558 scheme->wmarks.low = sysfs_wmarks->low;
1560 err = damon_sysfs_set_scheme_filters(scheme, sysfs_scheme->filters);
1562 damon_destroy_scheme(scheme);
1565 int damon_sysfs_set_schemes(struct damon_ctx *ctx,
1566 struct damon_sysfs_schemes *sysfs_schemes)
1568 struct damos *scheme, *next;
1571 damon_for_each_scheme_safe(scheme, next, ctx) {
1572 if (i < sysfs_schemes->nr)
1573 damon_sysfs_update_scheme(scheme,
1574 sysfs_schemes->schemes_arr[i]);
1576 damon_destroy_scheme(scheme);
1580 for (; i < sysfs_schemes->nr; i++) {
1581 struct damos *scheme, *next;
1583 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]);
1585 damon_for_each_scheme_safe(scheme, next, ctx)
1586 damon_destroy_scheme(scheme);
1589 damon_add_scheme(ctx, scheme);
1594 void damon_sysfs_schemes_update_stats(
1595 struct damon_sysfs_schemes *sysfs_schemes,
1596 struct damon_ctx *ctx)
1598 struct damos *scheme;
1599 int schemes_idx = 0;
1601 damon_for_each_scheme(scheme, ctx) {
1602 struct damon_sysfs_stats *sysfs_stats;
1604 /* user could have removed the scheme sysfs dir */
1605 if (schemes_idx >= sysfs_schemes->nr)
1608 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats;
1609 sysfs_stats->nr_tried = scheme->stat.nr_tried;
1610 sysfs_stats->sz_tried = scheme->stat.sz_tried;
1611 sysfs_stats->nr_applied = scheme->stat.nr_applied;
1612 sysfs_stats->sz_applied = scheme->stat.sz_applied;
1613 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds;
1618 * damon_sysfs_schemes that need to update its schemes regions dir. Protected
1619 * by damon_sysfs_lock
1621 static struct damon_sysfs_schemes *damon_sysfs_schemes_for_damos_callback;
1622 static int damon_sysfs_schemes_region_idx;
1625 * DAMON callback that called before damos apply. While this callback is
1626 * registered, damon_sysfs_lock should be held to ensure the regions
1627 * directories exist.
1629 static int damon_sysfs_before_damos_apply(struct damon_ctx *ctx,
1630 struct damon_target *t, struct damon_region *r,
1633 struct damos *scheme;
1634 struct damon_sysfs_scheme_regions *sysfs_regions;
1635 struct damon_sysfs_scheme_region *region;
1636 struct damon_sysfs_schemes *sysfs_schemes =
1637 damon_sysfs_schemes_for_damos_callback;
1638 int schemes_idx = 0;
1640 damon_for_each_scheme(scheme, ctx) {
1646 /* user could have removed the scheme sysfs dir */
1647 if (schemes_idx >= sysfs_schemes->nr)
1650 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions;
1651 region = damon_sysfs_scheme_region_alloc(r);
1652 list_add_tail(®ion->list, &sysfs_regions->regions_list);
1653 sysfs_regions->nr_regions++;
1654 if (kobject_init_and_add(®ion->kobj,
1655 &damon_sysfs_scheme_region_ktype,
1656 &sysfs_regions->kobj, "%d",
1657 damon_sysfs_schemes_region_idx++)) {
1658 kobject_put(®ion->kobj);
1663 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1664 int damon_sysfs_schemes_clear_regions(
1665 struct damon_sysfs_schemes *sysfs_schemes,
1666 struct damon_ctx *ctx)
1668 struct damos *scheme;
1669 int schemes_idx = 0;
1671 damon_for_each_scheme(scheme, ctx) {
1672 struct damon_sysfs_scheme *sysfs_scheme;
1674 /* user could have removed the scheme sysfs dir */
1675 if (schemes_idx >= sysfs_schemes->nr)
1678 sysfs_scheme = sysfs_schemes->schemes_arr[schemes_idx++];
1679 damon_sysfs_scheme_regions_rm_dirs(
1680 sysfs_scheme->tried_regions);
1685 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1686 int damon_sysfs_schemes_update_regions_start(
1687 struct damon_sysfs_schemes *sysfs_schemes,
1688 struct damon_ctx *ctx)
1690 damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx);
1691 damon_sysfs_schemes_for_damos_callback = sysfs_schemes;
1692 ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply;
1697 * Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock. Caller
1698 * should unlock damon_sysfs_lock which held before
1699 * damon_sysfs_schemes_update_regions_start()
1701 int damon_sysfs_schemes_update_regions_stop(struct damon_ctx *ctx)
1703 damon_sysfs_schemes_for_damos_callback = NULL;
1704 ctx->callback.before_damos_apply = NULL;
1705 damon_sysfs_schemes_region_idx = 0;