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;
120 unsigned long total_bytes;
123 static struct damon_sysfs_scheme_regions *
124 damon_sysfs_scheme_regions_alloc(void)
126 struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions),
132 regions->kobj = (struct kobject){};
133 INIT_LIST_HEAD(®ions->regions_list);
134 regions->nr_regions = 0;
135 regions->total_bytes = 0;
139 static ssize_t total_bytes_show(struct kobject *kobj,
140 struct kobj_attribute *attr, char *buf)
142 struct damon_sysfs_scheme_regions *regions = container_of(kobj,
143 struct damon_sysfs_scheme_regions, kobj);
145 return sysfs_emit(buf, "%lu\n", regions->total_bytes);
148 static void damon_sysfs_scheme_regions_rm_dirs(
149 struct damon_sysfs_scheme_regions *regions)
151 struct damon_sysfs_scheme_region *r, *next;
153 list_for_each_entry_safe(r, next, ®ions->regions_list, list) {
154 /* release function deletes it from the list */
155 kobject_put(&r->kobj);
156 regions->nr_regions--;
160 static void damon_sysfs_scheme_regions_release(struct kobject *kobj)
162 kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj));
165 static struct kobj_attribute damon_sysfs_scheme_regions_total_bytes_attr =
166 __ATTR_RO_MODE(total_bytes, 0400);
168 static struct attribute *damon_sysfs_scheme_regions_attrs[] = {
169 &damon_sysfs_scheme_regions_total_bytes_attr.attr,
172 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions);
174 static const struct kobj_type damon_sysfs_scheme_regions_ktype = {
175 .release = damon_sysfs_scheme_regions_release,
176 .sysfs_ops = &kobj_sysfs_ops,
177 .default_groups = damon_sysfs_scheme_regions_groups,
181 * schemes/stats directory
184 struct damon_sysfs_stats {
186 unsigned long nr_tried;
187 unsigned long sz_tried;
188 unsigned long nr_applied;
189 unsigned long sz_applied;
190 unsigned long qt_exceeds;
193 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void)
195 return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL);
198 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
201 struct damon_sysfs_stats *stats = container_of(kobj,
202 struct damon_sysfs_stats, kobj);
204 return sysfs_emit(buf, "%lu\n", stats->nr_tried);
207 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
210 struct damon_sysfs_stats *stats = container_of(kobj,
211 struct damon_sysfs_stats, kobj);
213 return sysfs_emit(buf, "%lu\n", stats->sz_tried);
216 static ssize_t nr_applied_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->nr_applied);
225 static ssize_t sz_applied_show(struct kobject *kobj,
226 struct kobj_attribute *attr, char *buf)
228 struct damon_sysfs_stats *stats = container_of(kobj,
229 struct damon_sysfs_stats, kobj);
231 return sysfs_emit(buf, "%lu\n", stats->sz_applied);
234 static ssize_t qt_exceeds_show(struct kobject *kobj,
235 struct kobj_attribute *attr, char *buf)
237 struct damon_sysfs_stats *stats = container_of(kobj,
238 struct damon_sysfs_stats, kobj);
240 return sysfs_emit(buf, "%lu\n", stats->qt_exceeds);
243 static void damon_sysfs_stats_release(struct kobject *kobj)
245 kfree(container_of(kobj, struct damon_sysfs_stats, kobj));
248 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr =
249 __ATTR_RO_MODE(nr_tried, 0400);
251 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr =
252 __ATTR_RO_MODE(sz_tried, 0400);
254 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr =
255 __ATTR_RO_MODE(nr_applied, 0400);
257 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr =
258 __ATTR_RO_MODE(sz_applied, 0400);
260 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr =
261 __ATTR_RO_MODE(qt_exceeds, 0400);
263 static struct attribute *damon_sysfs_stats_attrs[] = {
264 &damon_sysfs_stats_nr_tried_attr.attr,
265 &damon_sysfs_stats_sz_tried_attr.attr,
266 &damon_sysfs_stats_nr_applied_attr.attr,
267 &damon_sysfs_stats_sz_applied_attr.attr,
268 &damon_sysfs_stats_qt_exceeds_attr.attr,
271 ATTRIBUTE_GROUPS(damon_sysfs_stats);
273 static const struct kobj_type damon_sysfs_stats_ktype = {
274 .release = damon_sysfs_stats_release,
275 .sysfs_ops = &kobj_sysfs_ops,
276 .default_groups = damon_sysfs_stats_groups,
283 struct damon_sysfs_scheme_filter {
285 enum damos_filter_type type;
288 struct damon_addr_range addr_range;
292 static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc(void)
294 return kzalloc(sizeof(struct damon_sysfs_scheme_filter), GFP_KERNEL);
297 /* Should match with enum damos_filter_type */
298 static const char * const damon_sysfs_scheme_filter_type_strs[] = {
305 static ssize_t type_show(struct kobject *kobj,
306 struct kobj_attribute *attr, char *buf)
308 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
309 struct damon_sysfs_scheme_filter, kobj);
311 return sysfs_emit(buf, "%s\n",
312 damon_sysfs_scheme_filter_type_strs[filter->type]);
315 static ssize_t type_store(struct kobject *kobj,
316 struct kobj_attribute *attr, const char *buf, size_t count)
318 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
319 struct damon_sysfs_scheme_filter, kobj);
320 enum damos_filter_type type;
321 ssize_t ret = -EINVAL;
323 for (type = 0; type < NR_DAMOS_FILTER_TYPES; type++) {
324 if (sysfs_streq(buf, damon_sysfs_scheme_filter_type_strs[
334 static ssize_t matching_show(struct kobject *kobj,
335 struct kobj_attribute *attr, char *buf)
337 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
338 struct damon_sysfs_scheme_filter, kobj);
340 return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N');
343 static ssize_t matching_store(struct kobject *kobj,
344 struct kobj_attribute *attr, const char *buf, size_t count)
346 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
347 struct damon_sysfs_scheme_filter, kobj);
349 int err = kstrtobool(buf, &matching);
354 filter->matching = matching;
358 static ssize_t memcg_path_show(struct kobject *kobj,
359 struct kobj_attribute *attr, char *buf)
361 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
362 struct damon_sysfs_scheme_filter, kobj);
364 return sysfs_emit(buf, "%s\n",
365 filter->memcg_path ? filter->memcg_path : "");
368 static ssize_t memcg_path_store(struct kobject *kobj,
369 struct kobj_attribute *attr, const char *buf, size_t count)
371 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
372 struct damon_sysfs_scheme_filter, kobj);
373 char *path = kmalloc(sizeof(*path) * (count + 1), GFP_KERNEL);
378 strscpy(path, buf, count + 1);
379 filter->memcg_path = path;
383 static ssize_t addr_start_show(struct kobject *kobj,
384 struct kobj_attribute *attr, char *buf)
386 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
387 struct damon_sysfs_scheme_filter, kobj);
389 return sysfs_emit(buf, "%lu\n", filter->addr_range.start);
392 static ssize_t addr_start_store(struct kobject *kobj,
393 struct kobj_attribute *attr, const char *buf, size_t count)
395 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
396 struct damon_sysfs_scheme_filter, kobj);
397 int err = kstrtoul(buf, 0, &filter->addr_range.start);
399 return err ? err : count;
402 static ssize_t addr_end_show(struct kobject *kobj,
403 struct kobj_attribute *attr, char *buf)
405 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
406 struct damon_sysfs_scheme_filter, kobj);
408 return sysfs_emit(buf, "%lu\n", filter->addr_range.end);
411 static ssize_t addr_end_store(struct kobject *kobj,
412 struct kobj_attribute *attr, const char *buf, size_t count)
414 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
415 struct damon_sysfs_scheme_filter, kobj);
416 int err = kstrtoul(buf, 0, &filter->addr_range.end);
418 return err ? err : count;
421 static ssize_t damon_target_idx_show(struct kobject *kobj,
422 struct kobj_attribute *attr, char *buf)
424 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
425 struct damon_sysfs_scheme_filter, kobj);
427 return sysfs_emit(buf, "%d\n", filter->target_idx);
430 static ssize_t damon_target_idx_store(struct kobject *kobj,
431 struct kobj_attribute *attr, const char *buf, size_t count)
433 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
434 struct damon_sysfs_scheme_filter, kobj);
435 int err = kstrtoint(buf, 0, &filter->target_idx);
437 return err ? err : count;
440 static void damon_sysfs_scheme_filter_release(struct kobject *kobj)
442 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
443 struct damon_sysfs_scheme_filter, kobj);
445 kfree(filter->memcg_path);
449 static struct kobj_attribute damon_sysfs_scheme_filter_type_attr =
450 __ATTR_RW_MODE(type, 0600);
452 static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr =
453 __ATTR_RW_MODE(matching, 0600);
455 static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr =
456 __ATTR_RW_MODE(memcg_path, 0600);
458 static struct kobj_attribute damon_sysfs_scheme_filter_addr_start_attr =
459 __ATTR_RW_MODE(addr_start, 0600);
461 static struct kobj_attribute damon_sysfs_scheme_filter_addr_end_attr =
462 __ATTR_RW_MODE(addr_end, 0600);
464 static struct kobj_attribute damon_sysfs_scheme_filter_damon_target_idx_attr =
465 __ATTR_RW_MODE(damon_target_idx, 0600);
467 static struct attribute *damon_sysfs_scheme_filter_attrs[] = {
468 &damon_sysfs_scheme_filter_type_attr.attr,
469 &damon_sysfs_scheme_filter_matching_attr.attr,
470 &damon_sysfs_scheme_filter_memcg_path_attr.attr,
471 &damon_sysfs_scheme_filter_addr_start_attr.attr,
472 &damon_sysfs_scheme_filter_addr_end_attr.attr,
473 &damon_sysfs_scheme_filter_damon_target_idx_attr.attr,
476 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter);
478 static const struct kobj_type damon_sysfs_scheme_filter_ktype = {
479 .release = damon_sysfs_scheme_filter_release,
480 .sysfs_ops = &kobj_sysfs_ops,
481 .default_groups = damon_sysfs_scheme_filter_groups,
488 struct damon_sysfs_scheme_filters {
490 struct damon_sysfs_scheme_filter **filters_arr;
494 static struct damon_sysfs_scheme_filters *
495 damon_sysfs_scheme_filters_alloc(void)
497 return kzalloc(sizeof(struct damon_sysfs_scheme_filters), GFP_KERNEL);
500 static void damon_sysfs_scheme_filters_rm_dirs(
501 struct damon_sysfs_scheme_filters *filters)
503 struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr;
506 for (i = 0; i < filters->nr; i++)
507 kobject_put(&filters_arr[i]->kobj);
510 filters->filters_arr = NULL;
513 static int damon_sysfs_scheme_filters_add_dirs(
514 struct damon_sysfs_scheme_filters *filters, int nr_filters)
516 struct damon_sysfs_scheme_filter **filters_arr, *filter;
519 damon_sysfs_scheme_filters_rm_dirs(filters);
523 filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr),
524 GFP_KERNEL | __GFP_NOWARN);
527 filters->filters_arr = filters_arr;
529 for (i = 0; i < nr_filters; i++) {
530 filter = damon_sysfs_scheme_filter_alloc();
532 damon_sysfs_scheme_filters_rm_dirs(filters);
536 err = kobject_init_and_add(&filter->kobj,
537 &damon_sysfs_scheme_filter_ktype,
538 &filters->kobj, "%d", i);
540 kobject_put(&filter->kobj);
541 damon_sysfs_scheme_filters_rm_dirs(filters);
545 filters_arr[i] = filter;
551 static ssize_t nr_filters_show(struct kobject *kobj,
552 struct kobj_attribute *attr, char *buf)
554 struct damon_sysfs_scheme_filters *filters = container_of(kobj,
555 struct damon_sysfs_scheme_filters, kobj);
557 return sysfs_emit(buf, "%d\n", filters->nr);
560 static ssize_t nr_filters_store(struct kobject *kobj,
561 struct kobj_attribute *attr, const char *buf, size_t count)
563 struct damon_sysfs_scheme_filters *filters;
564 int nr, err = kstrtoint(buf, 0, &nr);
571 filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj);
573 if (!mutex_trylock(&damon_sysfs_lock))
575 err = damon_sysfs_scheme_filters_add_dirs(filters, nr);
576 mutex_unlock(&damon_sysfs_lock);
583 static void damon_sysfs_scheme_filters_release(struct kobject *kobj)
585 kfree(container_of(kobj, struct damon_sysfs_scheme_filters, kobj));
588 static struct kobj_attribute damon_sysfs_scheme_filters_nr_attr =
589 __ATTR_RW_MODE(nr_filters, 0600);
591 static struct attribute *damon_sysfs_scheme_filters_attrs[] = {
592 &damon_sysfs_scheme_filters_nr_attr.attr,
595 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filters);
597 static const struct kobj_type damon_sysfs_scheme_filters_ktype = {
598 .release = damon_sysfs_scheme_filters_release,
599 .sysfs_ops = &kobj_sysfs_ops,
600 .default_groups = damon_sysfs_scheme_filters_groups,
604 * watermarks directory
607 struct damon_sysfs_watermarks {
609 enum damos_wmark_metric metric;
610 unsigned long interval_us;
616 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
617 enum damos_wmark_metric metric, unsigned long interval_us,
618 unsigned long high, unsigned long mid, unsigned long low)
620 struct damon_sysfs_watermarks *watermarks = kmalloc(
621 sizeof(*watermarks), GFP_KERNEL);
625 watermarks->kobj = (struct kobject){};
626 watermarks->metric = metric;
627 watermarks->interval_us = interval_us;
628 watermarks->high = high;
629 watermarks->mid = mid;
630 watermarks->low = low;
634 /* Should match with enum damos_wmark_metric */
635 static const char * const damon_sysfs_wmark_metric_strs[] = {
640 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
643 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
644 struct damon_sysfs_watermarks, kobj);
646 return sysfs_emit(buf, "%s\n",
647 damon_sysfs_wmark_metric_strs[watermarks->metric]);
650 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
651 const char *buf, size_t count)
653 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
654 struct damon_sysfs_watermarks, kobj);
655 enum damos_wmark_metric metric;
657 for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) {
658 if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) {
659 watermarks->metric = metric;
666 static ssize_t interval_us_show(struct kobject *kobj,
667 struct kobj_attribute *attr, char *buf)
669 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
670 struct damon_sysfs_watermarks, kobj);
672 return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
675 static ssize_t interval_us_store(struct kobject *kobj,
676 struct kobj_attribute *attr, const char *buf, size_t count)
678 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
679 struct damon_sysfs_watermarks, kobj);
680 int err = kstrtoul(buf, 0, &watermarks->interval_us);
682 return err ? err : count;
685 static ssize_t high_show(struct kobject *kobj,
686 struct kobj_attribute *attr, char *buf)
688 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
689 struct damon_sysfs_watermarks, kobj);
691 return sysfs_emit(buf, "%lu\n", watermarks->high);
694 static ssize_t high_store(struct kobject *kobj,
695 struct kobj_attribute *attr, const char *buf, size_t count)
697 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
698 struct damon_sysfs_watermarks, kobj);
699 int err = kstrtoul(buf, 0, &watermarks->high);
701 return err ? err : count;
704 static ssize_t mid_show(struct kobject *kobj,
705 struct kobj_attribute *attr, char *buf)
707 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
708 struct damon_sysfs_watermarks, kobj);
710 return sysfs_emit(buf, "%lu\n", watermarks->mid);
713 static ssize_t mid_store(struct kobject *kobj,
714 struct kobj_attribute *attr, const char *buf, size_t count)
716 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
717 struct damon_sysfs_watermarks, kobj);
718 int err = kstrtoul(buf, 0, &watermarks->mid);
720 return err ? err : count;
723 static ssize_t low_show(struct kobject *kobj,
724 struct kobj_attribute *attr, char *buf)
726 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
727 struct damon_sysfs_watermarks, kobj);
729 return sysfs_emit(buf, "%lu\n", watermarks->low);
732 static ssize_t low_store(struct kobject *kobj,
733 struct kobj_attribute *attr, const char *buf, size_t count)
735 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
736 struct damon_sysfs_watermarks, kobj);
737 int err = kstrtoul(buf, 0, &watermarks->low);
739 return err ? err : count;
742 static void damon_sysfs_watermarks_release(struct kobject *kobj)
744 kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
747 static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
748 __ATTR_RW_MODE(metric, 0600);
750 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
751 __ATTR_RW_MODE(interval_us, 0600);
753 static struct kobj_attribute damon_sysfs_watermarks_high_attr =
754 __ATTR_RW_MODE(high, 0600);
756 static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
757 __ATTR_RW_MODE(mid, 0600);
759 static struct kobj_attribute damon_sysfs_watermarks_low_attr =
760 __ATTR_RW_MODE(low, 0600);
762 static struct attribute *damon_sysfs_watermarks_attrs[] = {
763 &damon_sysfs_watermarks_metric_attr.attr,
764 &damon_sysfs_watermarks_interval_us_attr.attr,
765 &damon_sysfs_watermarks_high_attr.attr,
766 &damon_sysfs_watermarks_mid_attr.attr,
767 &damon_sysfs_watermarks_low_attr.attr,
770 ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
772 static const struct kobj_type damon_sysfs_watermarks_ktype = {
773 .release = damon_sysfs_watermarks_release,
774 .sysfs_ops = &kobj_sysfs_ops,
775 .default_groups = damon_sysfs_watermarks_groups,
779 * scheme/weights directory
782 struct damon_sysfs_weights {
785 unsigned int nr_accesses;
789 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
790 unsigned int nr_accesses, unsigned int age)
792 struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
797 weights->kobj = (struct kobject){};
799 weights->nr_accesses = nr_accesses;
804 static ssize_t sz_permil_show(struct kobject *kobj,
805 struct kobj_attribute *attr, char *buf)
807 struct damon_sysfs_weights *weights = container_of(kobj,
808 struct damon_sysfs_weights, kobj);
810 return sysfs_emit(buf, "%u\n", weights->sz);
813 static ssize_t sz_permil_store(struct kobject *kobj,
814 struct kobj_attribute *attr, const char *buf, size_t count)
816 struct damon_sysfs_weights *weights = container_of(kobj,
817 struct damon_sysfs_weights, kobj);
818 int err = kstrtouint(buf, 0, &weights->sz);
820 return err ? err : count;
823 static ssize_t nr_accesses_permil_show(struct kobject *kobj,
824 struct kobj_attribute *attr, char *buf)
826 struct damon_sysfs_weights *weights = container_of(kobj,
827 struct damon_sysfs_weights, kobj);
829 return sysfs_emit(buf, "%u\n", weights->nr_accesses);
832 static ssize_t nr_accesses_permil_store(struct kobject *kobj,
833 struct kobj_attribute *attr, const char *buf, size_t count)
835 struct damon_sysfs_weights *weights = container_of(kobj,
836 struct damon_sysfs_weights, kobj);
837 int err = kstrtouint(buf, 0, &weights->nr_accesses);
839 return err ? err : count;
842 static ssize_t age_permil_show(struct kobject *kobj,
843 struct kobj_attribute *attr, char *buf)
845 struct damon_sysfs_weights *weights = container_of(kobj,
846 struct damon_sysfs_weights, kobj);
848 return sysfs_emit(buf, "%u\n", weights->age);
851 static ssize_t age_permil_store(struct kobject *kobj,
852 struct kobj_attribute *attr, const char *buf, size_t count)
854 struct damon_sysfs_weights *weights = container_of(kobj,
855 struct damon_sysfs_weights, kobj);
856 int err = kstrtouint(buf, 0, &weights->age);
858 return err ? err : count;
861 static void damon_sysfs_weights_release(struct kobject *kobj)
863 kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
866 static struct kobj_attribute damon_sysfs_weights_sz_attr =
867 __ATTR_RW_MODE(sz_permil, 0600);
869 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
870 __ATTR_RW_MODE(nr_accesses_permil, 0600);
872 static struct kobj_attribute damon_sysfs_weights_age_attr =
873 __ATTR_RW_MODE(age_permil, 0600);
875 static struct attribute *damon_sysfs_weights_attrs[] = {
876 &damon_sysfs_weights_sz_attr.attr,
877 &damon_sysfs_weights_nr_accesses_attr.attr,
878 &damon_sysfs_weights_age_attr.attr,
881 ATTRIBUTE_GROUPS(damon_sysfs_weights);
883 static const struct kobj_type damon_sysfs_weights_ktype = {
884 .release = damon_sysfs_weights_release,
885 .sysfs_ops = &kobj_sysfs_ops,
886 .default_groups = damon_sysfs_weights_groups,
893 struct damon_sysfs_quotas {
895 struct damon_sysfs_weights *weights;
898 unsigned long reset_interval_ms;
901 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
903 return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
906 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
908 struct damon_sysfs_weights *weights;
911 weights = damon_sysfs_weights_alloc(0, 0, 0);
915 err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
916 "as->kobj, "weights");
918 kobject_put(&weights->kobj);
920 quotas->weights = weights;
924 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
926 kobject_put("as->weights->kobj);
929 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
932 struct damon_sysfs_quotas *quotas = container_of(kobj,
933 struct damon_sysfs_quotas, kobj);
935 return sysfs_emit(buf, "%lu\n", quotas->ms);
938 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
939 const char *buf, size_t count)
941 struct damon_sysfs_quotas *quotas = container_of(kobj,
942 struct damon_sysfs_quotas, kobj);
943 int err = kstrtoul(buf, 0, "as->ms);
950 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
953 struct damon_sysfs_quotas *quotas = container_of(kobj,
954 struct damon_sysfs_quotas, kobj);
956 return sysfs_emit(buf, "%lu\n", quotas->sz);
959 static ssize_t bytes_store(struct kobject *kobj,
960 struct kobj_attribute *attr, const char *buf, size_t count)
962 struct damon_sysfs_quotas *quotas = container_of(kobj,
963 struct damon_sysfs_quotas, kobj);
964 int err = kstrtoul(buf, 0, "as->sz);
971 static ssize_t reset_interval_ms_show(struct kobject *kobj,
972 struct kobj_attribute *attr, char *buf)
974 struct damon_sysfs_quotas *quotas = container_of(kobj,
975 struct damon_sysfs_quotas, kobj);
977 return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
980 static ssize_t reset_interval_ms_store(struct kobject *kobj,
981 struct kobj_attribute *attr, const char *buf, size_t count)
983 struct damon_sysfs_quotas *quotas = container_of(kobj,
984 struct damon_sysfs_quotas, kobj);
985 int err = kstrtoul(buf, 0, "as->reset_interval_ms);
992 static void damon_sysfs_quotas_release(struct kobject *kobj)
994 kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
997 static struct kobj_attribute damon_sysfs_quotas_ms_attr =
998 __ATTR_RW_MODE(ms, 0600);
1000 static struct kobj_attribute damon_sysfs_quotas_sz_attr =
1001 __ATTR_RW_MODE(bytes, 0600);
1003 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
1004 __ATTR_RW_MODE(reset_interval_ms, 0600);
1006 static struct attribute *damon_sysfs_quotas_attrs[] = {
1007 &damon_sysfs_quotas_ms_attr.attr,
1008 &damon_sysfs_quotas_sz_attr.attr,
1009 &damon_sysfs_quotas_reset_interval_ms_attr.attr,
1012 ATTRIBUTE_GROUPS(damon_sysfs_quotas);
1014 static const struct kobj_type damon_sysfs_quotas_ktype = {
1015 .release = damon_sysfs_quotas_release,
1016 .sysfs_ops = &kobj_sysfs_ops,
1017 .default_groups = damon_sysfs_quotas_groups,
1021 * access_pattern directory
1024 struct damon_sysfs_access_pattern {
1025 struct kobject kobj;
1026 struct damon_sysfs_ul_range *sz;
1027 struct damon_sysfs_ul_range *nr_accesses;
1028 struct damon_sysfs_ul_range *age;
1032 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void)
1034 struct damon_sysfs_access_pattern *access_pattern =
1035 kmalloc(sizeof(*access_pattern), GFP_KERNEL);
1037 if (!access_pattern)
1039 access_pattern->kobj = (struct kobject){};
1040 return access_pattern;
1043 static int damon_sysfs_access_pattern_add_range_dir(
1044 struct damon_sysfs_access_pattern *access_pattern,
1045 struct damon_sysfs_ul_range **range_dir_ptr,
1048 struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0);
1053 err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype,
1054 &access_pattern->kobj, name);
1056 kobject_put(&range->kobj);
1058 *range_dir_ptr = range;
1062 static int damon_sysfs_access_pattern_add_dirs(
1063 struct damon_sysfs_access_pattern *access_pattern)
1067 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1068 &access_pattern->sz, "sz");
1072 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1073 &access_pattern->nr_accesses, "nr_accesses");
1075 goto put_nr_accesses_sz_out;
1077 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1078 &access_pattern->age, "age");
1080 goto put_age_nr_accesses_sz_out;
1083 put_age_nr_accesses_sz_out:
1084 kobject_put(&access_pattern->age->kobj);
1085 access_pattern->age = NULL;
1086 put_nr_accesses_sz_out:
1087 kobject_put(&access_pattern->nr_accesses->kobj);
1088 access_pattern->nr_accesses = NULL;
1090 kobject_put(&access_pattern->sz->kobj);
1091 access_pattern->sz = NULL;
1095 static void damon_sysfs_access_pattern_rm_dirs(
1096 struct damon_sysfs_access_pattern *access_pattern)
1098 kobject_put(&access_pattern->sz->kobj);
1099 kobject_put(&access_pattern->nr_accesses->kobj);
1100 kobject_put(&access_pattern->age->kobj);
1103 static void damon_sysfs_access_pattern_release(struct kobject *kobj)
1105 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj));
1108 static struct attribute *damon_sysfs_access_pattern_attrs[] = {
1111 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern);
1113 static const struct kobj_type damon_sysfs_access_pattern_ktype = {
1114 .release = damon_sysfs_access_pattern_release,
1115 .sysfs_ops = &kobj_sysfs_ops,
1116 .default_groups = damon_sysfs_access_pattern_groups,
1123 struct damon_sysfs_scheme {
1124 struct kobject kobj;
1125 enum damos_action action;
1126 struct damon_sysfs_access_pattern *access_pattern;
1127 struct damon_sysfs_quotas *quotas;
1128 struct damon_sysfs_watermarks *watermarks;
1129 struct damon_sysfs_scheme_filters *filters;
1130 struct damon_sysfs_stats *stats;
1131 struct damon_sysfs_scheme_regions *tried_regions;
1134 /* This should match with enum damos_action */
1135 static const char * const damon_sysfs_damos_action_strs[] = {
1146 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
1147 enum damos_action action)
1149 struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme),
1154 scheme->kobj = (struct kobject){};
1155 scheme->action = action;
1159 static int damon_sysfs_scheme_set_access_pattern(
1160 struct damon_sysfs_scheme *scheme)
1162 struct damon_sysfs_access_pattern *access_pattern;
1165 access_pattern = damon_sysfs_access_pattern_alloc();
1166 if (!access_pattern)
1168 err = kobject_init_and_add(&access_pattern->kobj,
1169 &damon_sysfs_access_pattern_ktype, &scheme->kobj,
1173 err = damon_sysfs_access_pattern_add_dirs(access_pattern);
1176 scheme->access_pattern = access_pattern;
1180 kobject_put(&access_pattern->kobj);
1184 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
1186 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
1191 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype,
1192 &scheme->kobj, "quotas");
1195 err = damon_sysfs_quotas_add_dirs(quotas);
1198 scheme->quotas = quotas;
1202 kobject_put("as->kobj);
1206 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
1208 struct damon_sysfs_watermarks *watermarks =
1209 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
1214 err = kobject_init_and_add(&watermarks->kobj,
1215 &damon_sysfs_watermarks_ktype, &scheme->kobj,
1218 kobject_put(&watermarks->kobj);
1220 scheme->watermarks = watermarks;
1224 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme)
1226 struct damon_sysfs_scheme_filters *filters =
1227 damon_sysfs_scheme_filters_alloc();
1232 err = kobject_init_and_add(&filters->kobj,
1233 &damon_sysfs_scheme_filters_ktype, &scheme->kobj,
1236 kobject_put(&filters->kobj);
1238 scheme->filters = filters;
1242 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme)
1244 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc();
1249 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype,
1250 &scheme->kobj, "stats");
1252 kobject_put(&stats->kobj);
1254 scheme->stats = stats;
1258 static int damon_sysfs_scheme_set_tried_regions(
1259 struct damon_sysfs_scheme *scheme)
1261 struct damon_sysfs_scheme_regions *tried_regions =
1262 damon_sysfs_scheme_regions_alloc();
1267 err = kobject_init_and_add(&tried_regions->kobj,
1268 &damon_sysfs_scheme_regions_ktype, &scheme->kobj,
1271 kobject_put(&tried_regions->kobj);
1273 scheme->tried_regions = tried_regions;
1277 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
1281 err = damon_sysfs_scheme_set_access_pattern(scheme);
1284 err = damon_sysfs_scheme_set_quotas(scheme);
1286 goto put_access_pattern_out;
1287 err = damon_sysfs_scheme_set_watermarks(scheme);
1289 goto put_quotas_access_pattern_out;
1290 err = damon_sysfs_scheme_set_filters(scheme);
1292 goto put_watermarks_quotas_access_pattern_out;
1293 err = damon_sysfs_scheme_set_stats(scheme);
1295 goto put_filters_watermarks_quotas_access_pattern_out;
1296 err = damon_sysfs_scheme_set_tried_regions(scheme);
1298 goto put_tried_regions_out;
1301 put_tried_regions_out:
1302 kobject_put(&scheme->tried_regions->kobj);
1303 scheme->tried_regions = NULL;
1304 put_filters_watermarks_quotas_access_pattern_out:
1305 kobject_put(&scheme->filters->kobj);
1306 scheme->filters = NULL;
1307 put_watermarks_quotas_access_pattern_out:
1308 kobject_put(&scheme->watermarks->kobj);
1309 scheme->watermarks = NULL;
1310 put_quotas_access_pattern_out:
1311 kobject_put(&scheme->quotas->kobj);
1312 scheme->quotas = NULL;
1313 put_access_pattern_out:
1314 kobject_put(&scheme->access_pattern->kobj);
1315 scheme->access_pattern = NULL;
1319 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
1321 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
1322 kobject_put(&scheme->access_pattern->kobj);
1323 damon_sysfs_quotas_rm_dirs(scheme->quotas);
1324 kobject_put(&scheme->quotas->kobj);
1325 kobject_put(&scheme->watermarks->kobj);
1326 damon_sysfs_scheme_filters_rm_dirs(scheme->filters);
1327 kobject_put(&scheme->filters->kobj);
1328 kobject_put(&scheme->stats->kobj);
1329 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions);
1330 kobject_put(&scheme->tried_regions->kobj);
1333 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
1336 struct damon_sysfs_scheme *scheme = container_of(kobj,
1337 struct damon_sysfs_scheme, kobj);
1339 return sysfs_emit(buf, "%s\n",
1340 damon_sysfs_damos_action_strs[scheme->action]);
1343 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr,
1344 const char *buf, size_t count)
1346 struct damon_sysfs_scheme *scheme = container_of(kobj,
1347 struct damon_sysfs_scheme, kobj);
1348 enum damos_action action;
1350 for (action = 0; action < NR_DAMOS_ACTIONS; action++) {
1351 if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) {
1352 scheme->action = action;
1359 static void damon_sysfs_scheme_release(struct kobject *kobj)
1361 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
1364 static struct kobj_attribute damon_sysfs_scheme_action_attr =
1365 __ATTR_RW_MODE(action, 0600);
1367 static struct attribute *damon_sysfs_scheme_attrs[] = {
1368 &damon_sysfs_scheme_action_attr.attr,
1371 ATTRIBUTE_GROUPS(damon_sysfs_scheme);
1373 static const struct kobj_type damon_sysfs_scheme_ktype = {
1374 .release = damon_sysfs_scheme_release,
1375 .sysfs_ops = &kobj_sysfs_ops,
1376 .default_groups = damon_sysfs_scheme_groups,
1383 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void)
1385 return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL);
1388 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes)
1390 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr;
1393 for (i = 0; i < schemes->nr; i++) {
1394 damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
1395 kobject_put(&schemes_arr[i]->kobj);
1399 schemes->schemes_arr = NULL;
1402 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes,
1405 struct damon_sysfs_scheme **schemes_arr, *scheme;
1408 damon_sysfs_schemes_rm_dirs(schemes);
1412 schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr),
1413 GFP_KERNEL | __GFP_NOWARN);
1416 schemes->schemes_arr = schemes_arr;
1418 for (i = 0; i < nr_schemes; i++) {
1419 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT);
1421 damon_sysfs_schemes_rm_dirs(schemes);
1425 err = kobject_init_and_add(&scheme->kobj,
1426 &damon_sysfs_scheme_ktype, &schemes->kobj,
1430 err = damon_sysfs_scheme_add_dirs(scheme);
1434 schemes_arr[i] = scheme;
1440 damon_sysfs_schemes_rm_dirs(schemes);
1441 kobject_put(&scheme->kobj);
1445 static ssize_t nr_schemes_show(struct kobject *kobj,
1446 struct kobj_attribute *attr, char *buf)
1448 struct damon_sysfs_schemes *schemes = container_of(kobj,
1449 struct damon_sysfs_schemes, kobj);
1451 return sysfs_emit(buf, "%d\n", schemes->nr);
1454 static ssize_t nr_schemes_store(struct kobject *kobj,
1455 struct kobj_attribute *attr, const char *buf, size_t count)
1457 struct damon_sysfs_schemes *schemes;
1458 int nr, err = kstrtoint(buf, 0, &nr);
1465 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj);
1467 if (!mutex_trylock(&damon_sysfs_lock))
1469 err = damon_sysfs_schemes_add_dirs(schemes, nr);
1470 mutex_unlock(&damon_sysfs_lock);
1476 static void damon_sysfs_schemes_release(struct kobject *kobj)
1478 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj));
1481 static struct kobj_attribute damon_sysfs_schemes_nr_attr =
1482 __ATTR_RW_MODE(nr_schemes, 0600);
1484 static struct attribute *damon_sysfs_schemes_attrs[] = {
1485 &damon_sysfs_schemes_nr_attr.attr,
1488 ATTRIBUTE_GROUPS(damon_sysfs_schemes);
1490 const struct kobj_type damon_sysfs_schemes_ktype = {
1491 .release = damon_sysfs_schemes_release,
1492 .sysfs_ops = &kobj_sysfs_ops,
1493 .default_groups = damon_sysfs_schemes_groups,
1496 static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg,
1497 char *memcg_path_buf, char *path)
1500 cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX);
1501 if (sysfs_streq(memcg_path_buf, path))
1503 #endif /* CONFIG_MEMCG */
1507 static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id)
1509 struct mem_cgroup *memcg;
1516 path = kmalloc(sizeof(*path) * PATH_MAX, GFP_KERNEL);
1520 for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg;
1521 memcg = mem_cgroup_iter(NULL, memcg, NULL)) {
1522 /* skip removed memcg */
1523 if (!mem_cgroup_id(memcg))
1525 if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) {
1526 *id = mem_cgroup_id(memcg);
1533 return found ? 0 : -EINVAL;
1536 static int damon_sysfs_set_scheme_filters(struct damos *scheme,
1537 struct damon_sysfs_scheme_filters *sysfs_filters)
1540 struct damos_filter *filter, *next;
1542 damos_for_each_filter_safe(filter, next, scheme)
1543 damos_destroy_filter(filter);
1545 for (i = 0; i < sysfs_filters->nr; i++) {
1546 struct damon_sysfs_scheme_filter *sysfs_filter =
1547 sysfs_filters->filters_arr[i];
1548 struct damos_filter *filter =
1549 damos_new_filter(sysfs_filter->type,
1550 sysfs_filter->matching);
1555 if (filter->type == DAMOS_FILTER_TYPE_MEMCG) {
1556 err = damon_sysfs_memcg_path_to_id(
1557 sysfs_filter->memcg_path,
1560 damos_destroy_filter(filter);
1563 } else if (filter->type == DAMOS_FILTER_TYPE_ADDR) {
1564 if (sysfs_filter->addr_range.end <
1565 sysfs_filter->addr_range.start) {
1566 damos_destroy_filter(filter);
1569 filter->addr_range = sysfs_filter->addr_range;
1570 } else if (filter->type == DAMOS_FILTER_TYPE_TARGET) {
1571 filter->target_idx = sysfs_filter->target_idx;
1574 damos_add_filter(scheme, filter);
1579 static struct damos *damon_sysfs_mk_scheme(
1580 struct damon_sysfs_scheme *sysfs_scheme)
1582 struct damon_sysfs_access_pattern *access_pattern =
1583 sysfs_scheme->access_pattern;
1584 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1585 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1586 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1587 struct damon_sysfs_scheme_filters *sysfs_filters =
1588 sysfs_scheme->filters;
1589 struct damos *scheme;
1592 struct damos_access_pattern pattern = {
1593 .min_sz_region = access_pattern->sz->min,
1594 .max_sz_region = access_pattern->sz->max,
1595 .min_nr_accesses = access_pattern->nr_accesses->min,
1596 .max_nr_accesses = access_pattern->nr_accesses->max,
1597 .min_age_region = access_pattern->age->min,
1598 .max_age_region = access_pattern->age->max,
1600 struct damos_quota quota = {
1601 .ms = sysfs_quotas->ms,
1602 .sz = sysfs_quotas->sz,
1603 .reset_interval = sysfs_quotas->reset_interval_ms,
1604 .weight_sz = sysfs_weights->sz,
1605 .weight_nr_accesses = sysfs_weights->nr_accesses,
1606 .weight_age = sysfs_weights->age,
1608 struct damos_watermarks wmarks = {
1609 .metric = sysfs_wmarks->metric,
1610 .interval = sysfs_wmarks->interval_us,
1611 .high = sysfs_wmarks->high,
1612 .mid = sysfs_wmarks->mid,
1613 .low = sysfs_wmarks->low,
1616 scheme = damon_new_scheme(&pattern, sysfs_scheme->action, "a,
1621 err = damon_sysfs_set_scheme_filters(scheme, sysfs_filters);
1623 damon_destroy_scheme(scheme);
1629 static void damon_sysfs_update_scheme(struct damos *scheme,
1630 struct damon_sysfs_scheme *sysfs_scheme)
1632 struct damon_sysfs_access_pattern *access_pattern =
1633 sysfs_scheme->access_pattern;
1634 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1635 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1636 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1639 scheme->pattern.min_sz_region = access_pattern->sz->min;
1640 scheme->pattern.max_sz_region = access_pattern->sz->max;
1641 scheme->pattern.min_nr_accesses = access_pattern->nr_accesses->min;
1642 scheme->pattern.max_nr_accesses = access_pattern->nr_accesses->max;
1643 scheme->pattern.min_age_region = access_pattern->age->min;
1644 scheme->pattern.max_age_region = access_pattern->age->max;
1646 scheme->action = sysfs_scheme->action;
1648 scheme->quota.ms = sysfs_quotas->ms;
1649 scheme->quota.sz = sysfs_quotas->sz;
1650 scheme->quota.reset_interval = sysfs_quotas->reset_interval_ms;
1651 scheme->quota.weight_sz = sysfs_weights->sz;
1652 scheme->quota.weight_nr_accesses = sysfs_weights->nr_accesses;
1653 scheme->quota.weight_age = sysfs_weights->age;
1655 scheme->wmarks.metric = sysfs_wmarks->metric;
1656 scheme->wmarks.interval = sysfs_wmarks->interval_us;
1657 scheme->wmarks.high = sysfs_wmarks->high;
1658 scheme->wmarks.mid = sysfs_wmarks->mid;
1659 scheme->wmarks.low = sysfs_wmarks->low;
1661 err = damon_sysfs_set_scheme_filters(scheme, sysfs_scheme->filters);
1663 damon_destroy_scheme(scheme);
1666 int damon_sysfs_set_schemes(struct damon_ctx *ctx,
1667 struct damon_sysfs_schemes *sysfs_schemes)
1669 struct damos *scheme, *next;
1672 damon_for_each_scheme_safe(scheme, next, ctx) {
1673 if (i < sysfs_schemes->nr)
1674 damon_sysfs_update_scheme(scheme,
1675 sysfs_schemes->schemes_arr[i]);
1677 damon_destroy_scheme(scheme);
1681 for (; i < sysfs_schemes->nr; i++) {
1682 struct damos *scheme, *next;
1684 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]);
1686 damon_for_each_scheme_safe(scheme, next, ctx)
1687 damon_destroy_scheme(scheme);
1690 damon_add_scheme(ctx, scheme);
1695 void damon_sysfs_schemes_update_stats(
1696 struct damon_sysfs_schemes *sysfs_schemes,
1697 struct damon_ctx *ctx)
1699 struct damos *scheme;
1700 int schemes_idx = 0;
1702 damon_for_each_scheme(scheme, ctx) {
1703 struct damon_sysfs_stats *sysfs_stats;
1705 /* user could have removed the scheme sysfs dir */
1706 if (schemes_idx >= sysfs_schemes->nr)
1709 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats;
1710 sysfs_stats->nr_tried = scheme->stat.nr_tried;
1711 sysfs_stats->sz_tried = scheme->stat.sz_tried;
1712 sysfs_stats->nr_applied = scheme->stat.nr_applied;
1713 sysfs_stats->sz_applied = scheme->stat.sz_applied;
1714 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds;
1719 * damon_sysfs_schemes that need to update its schemes regions dir. Protected
1720 * by damon_sysfs_lock
1722 static struct damon_sysfs_schemes *damon_sysfs_schemes_for_damos_callback;
1723 static int damon_sysfs_schemes_region_idx;
1724 static bool damos_regions_upd_total_bytes_only;
1727 * DAMON callback that called before damos apply. While this callback is
1728 * registered, damon_sysfs_lock should be held to ensure the regions
1729 * directories exist.
1731 static int damon_sysfs_before_damos_apply(struct damon_ctx *ctx,
1732 struct damon_target *t, struct damon_region *r,
1735 struct damos *scheme;
1736 struct damon_sysfs_scheme_regions *sysfs_regions;
1737 struct damon_sysfs_scheme_region *region;
1738 struct damon_sysfs_schemes *sysfs_schemes =
1739 damon_sysfs_schemes_for_damos_callback;
1740 int schemes_idx = 0;
1742 damon_for_each_scheme(scheme, ctx) {
1748 /* user could have removed the scheme sysfs dir */
1749 if (schemes_idx >= sysfs_schemes->nr)
1752 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions;
1753 sysfs_regions->total_bytes += r->ar.end - r->ar.start;
1754 if (damos_regions_upd_total_bytes_only)
1757 region = damon_sysfs_scheme_region_alloc(r);
1760 list_add_tail(®ion->list, &sysfs_regions->regions_list);
1761 sysfs_regions->nr_regions++;
1762 if (kobject_init_and_add(®ion->kobj,
1763 &damon_sysfs_scheme_region_ktype,
1764 &sysfs_regions->kobj, "%d",
1765 damon_sysfs_schemes_region_idx++)) {
1766 kobject_put(®ion->kobj);
1771 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1772 int damon_sysfs_schemes_clear_regions(
1773 struct damon_sysfs_schemes *sysfs_schemes,
1774 struct damon_ctx *ctx)
1776 struct damos *scheme;
1777 int schemes_idx = 0;
1779 damon_for_each_scheme(scheme, ctx) {
1780 struct damon_sysfs_scheme *sysfs_scheme;
1782 /* user could have removed the scheme sysfs dir */
1783 if (schemes_idx >= sysfs_schemes->nr)
1786 sysfs_scheme = sysfs_schemes->schemes_arr[schemes_idx++];
1787 damon_sysfs_scheme_regions_rm_dirs(
1788 sysfs_scheme->tried_regions);
1789 sysfs_scheme->tried_regions->total_bytes = 0;
1794 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1795 int damon_sysfs_schemes_update_regions_start(
1796 struct damon_sysfs_schemes *sysfs_schemes,
1797 struct damon_ctx *ctx, bool total_bytes_only)
1799 damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx);
1800 damon_sysfs_schemes_for_damos_callback = sysfs_schemes;
1801 damos_regions_upd_total_bytes_only = total_bytes_only;
1802 ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply;
1807 * Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock. Caller
1808 * should unlock damon_sysfs_lock which held before
1809 * damon_sysfs_schemes_update_regions_start()
1811 int damon_sysfs_schemes_update_regions_stop(struct damon_ctx *ctx)
1813 damon_sysfs_schemes_for_damos_callback = NULL;
1814 ctx->callback.before_damos_apply = NULL;
1815 damon_sysfs_schemes_region_idx = 0;