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),
129 regions->kobj = (struct kobject){};
130 INIT_LIST_HEAD(®ions->regions_list);
131 regions->nr_regions = 0;
132 regions->total_bytes = 0;
136 static ssize_t total_bytes_show(struct kobject *kobj,
137 struct kobj_attribute *attr, char *buf)
139 struct damon_sysfs_scheme_regions *regions = container_of(kobj,
140 struct damon_sysfs_scheme_regions, kobj);
142 return sysfs_emit(buf, "%lu\n", regions->total_bytes);
145 static void damon_sysfs_scheme_regions_rm_dirs(
146 struct damon_sysfs_scheme_regions *regions)
148 struct damon_sysfs_scheme_region *r, *next;
150 list_for_each_entry_safe(r, next, ®ions->regions_list, list) {
151 /* release function deletes it from the list */
152 kobject_put(&r->kobj);
153 regions->nr_regions--;
157 static void damon_sysfs_scheme_regions_release(struct kobject *kobj)
159 kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj));
162 static struct kobj_attribute damon_sysfs_scheme_regions_total_bytes_attr =
163 __ATTR_RO_MODE(total_bytes, 0400);
165 static struct attribute *damon_sysfs_scheme_regions_attrs[] = {
166 &damon_sysfs_scheme_regions_total_bytes_attr.attr,
169 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions);
171 static const struct kobj_type damon_sysfs_scheme_regions_ktype = {
172 .release = damon_sysfs_scheme_regions_release,
173 .sysfs_ops = &kobj_sysfs_ops,
174 .default_groups = damon_sysfs_scheme_regions_groups,
178 * schemes/stats directory
181 struct damon_sysfs_stats {
183 unsigned long nr_tried;
184 unsigned long sz_tried;
185 unsigned long nr_applied;
186 unsigned long sz_applied;
187 unsigned long qt_exceeds;
190 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void)
192 return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL);
195 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
198 struct damon_sysfs_stats *stats = container_of(kobj,
199 struct damon_sysfs_stats, kobj);
201 return sysfs_emit(buf, "%lu\n", stats->nr_tried);
204 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
207 struct damon_sysfs_stats *stats = container_of(kobj,
208 struct damon_sysfs_stats, kobj);
210 return sysfs_emit(buf, "%lu\n", stats->sz_tried);
213 static ssize_t nr_applied_show(struct kobject *kobj,
214 struct kobj_attribute *attr, char *buf)
216 struct damon_sysfs_stats *stats = container_of(kobj,
217 struct damon_sysfs_stats, kobj);
219 return sysfs_emit(buf, "%lu\n", stats->nr_applied);
222 static ssize_t sz_applied_show(struct kobject *kobj,
223 struct kobj_attribute *attr, char *buf)
225 struct damon_sysfs_stats *stats = container_of(kobj,
226 struct damon_sysfs_stats, kobj);
228 return sysfs_emit(buf, "%lu\n", stats->sz_applied);
231 static ssize_t qt_exceeds_show(struct kobject *kobj,
232 struct kobj_attribute *attr, char *buf)
234 struct damon_sysfs_stats *stats = container_of(kobj,
235 struct damon_sysfs_stats, kobj);
237 return sysfs_emit(buf, "%lu\n", stats->qt_exceeds);
240 static void damon_sysfs_stats_release(struct kobject *kobj)
242 kfree(container_of(kobj, struct damon_sysfs_stats, kobj));
245 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr =
246 __ATTR_RO_MODE(nr_tried, 0400);
248 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr =
249 __ATTR_RO_MODE(sz_tried, 0400);
251 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr =
252 __ATTR_RO_MODE(nr_applied, 0400);
254 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr =
255 __ATTR_RO_MODE(sz_applied, 0400);
257 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr =
258 __ATTR_RO_MODE(qt_exceeds, 0400);
260 static struct attribute *damon_sysfs_stats_attrs[] = {
261 &damon_sysfs_stats_nr_tried_attr.attr,
262 &damon_sysfs_stats_sz_tried_attr.attr,
263 &damon_sysfs_stats_nr_applied_attr.attr,
264 &damon_sysfs_stats_sz_applied_attr.attr,
265 &damon_sysfs_stats_qt_exceeds_attr.attr,
268 ATTRIBUTE_GROUPS(damon_sysfs_stats);
270 static const struct kobj_type damon_sysfs_stats_ktype = {
271 .release = damon_sysfs_stats_release,
272 .sysfs_ops = &kobj_sysfs_ops,
273 .default_groups = damon_sysfs_stats_groups,
280 struct damon_sysfs_scheme_filter {
282 enum damos_filter_type type;
285 struct damon_addr_range addr_range;
289 static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc(void)
291 return kzalloc(sizeof(struct damon_sysfs_scheme_filter), GFP_KERNEL);
294 /* Should match with enum damos_filter_type */
295 static const char * const damon_sysfs_scheme_filter_type_strs[] = {
302 static ssize_t type_show(struct kobject *kobj,
303 struct kobj_attribute *attr, char *buf)
305 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
306 struct damon_sysfs_scheme_filter, kobj);
308 return sysfs_emit(buf, "%s\n",
309 damon_sysfs_scheme_filter_type_strs[filter->type]);
312 static ssize_t type_store(struct kobject *kobj,
313 struct kobj_attribute *attr, const char *buf, size_t count)
315 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
316 struct damon_sysfs_scheme_filter, kobj);
317 enum damos_filter_type type;
318 ssize_t ret = -EINVAL;
320 for (type = 0; type < NR_DAMOS_FILTER_TYPES; type++) {
321 if (sysfs_streq(buf, damon_sysfs_scheme_filter_type_strs[
331 static ssize_t matching_show(struct kobject *kobj,
332 struct kobj_attribute *attr, char *buf)
334 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
335 struct damon_sysfs_scheme_filter, kobj);
337 return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N');
340 static ssize_t matching_store(struct kobject *kobj,
341 struct kobj_attribute *attr, const char *buf, size_t count)
343 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
344 struct damon_sysfs_scheme_filter, kobj);
346 int err = kstrtobool(buf, &matching);
351 filter->matching = matching;
355 static ssize_t memcg_path_show(struct kobject *kobj,
356 struct kobj_attribute *attr, char *buf)
358 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
359 struct damon_sysfs_scheme_filter, kobj);
361 return sysfs_emit(buf, "%s\n",
362 filter->memcg_path ? filter->memcg_path : "");
365 static ssize_t memcg_path_store(struct kobject *kobj,
366 struct kobj_attribute *attr, const char *buf, size_t count)
368 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
369 struct damon_sysfs_scheme_filter, kobj);
370 char *path = kmalloc(sizeof(*path) * (count + 1), GFP_KERNEL);
375 strscpy(path, buf, count + 1);
376 filter->memcg_path = path;
380 static ssize_t addr_start_show(struct kobject *kobj,
381 struct kobj_attribute *attr, char *buf)
383 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
384 struct damon_sysfs_scheme_filter, kobj);
386 return sysfs_emit(buf, "%lu\n", filter->addr_range.start);
389 static ssize_t addr_start_store(struct kobject *kobj,
390 struct kobj_attribute *attr, const char *buf, size_t count)
392 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
393 struct damon_sysfs_scheme_filter, kobj);
394 int err = kstrtoul(buf, 0, &filter->addr_range.start);
396 return err ? err : count;
399 static ssize_t addr_end_show(struct kobject *kobj,
400 struct kobj_attribute *attr, char *buf)
402 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
403 struct damon_sysfs_scheme_filter, kobj);
405 return sysfs_emit(buf, "%lu\n", filter->addr_range.end);
408 static ssize_t addr_end_store(struct kobject *kobj,
409 struct kobj_attribute *attr, const char *buf, size_t count)
411 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
412 struct damon_sysfs_scheme_filter, kobj);
413 int err = kstrtoul(buf, 0, &filter->addr_range.end);
415 return err ? err : count;
418 static ssize_t damon_target_idx_show(struct kobject *kobj,
419 struct kobj_attribute *attr, char *buf)
421 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
422 struct damon_sysfs_scheme_filter, kobj);
424 return sysfs_emit(buf, "%d\n", filter->target_idx);
427 static ssize_t damon_target_idx_store(struct kobject *kobj,
428 struct kobj_attribute *attr, const char *buf, size_t count)
430 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
431 struct damon_sysfs_scheme_filter, kobj);
432 int err = kstrtoint(buf, 0, &filter->target_idx);
434 return err ? err : count;
437 static void damon_sysfs_scheme_filter_release(struct kobject *kobj)
439 struct damon_sysfs_scheme_filter *filter = container_of(kobj,
440 struct damon_sysfs_scheme_filter, kobj);
442 kfree(filter->memcg_path);
446 static struct kobj_attribute damon_sysfs_scheme_filter_type_attr =
447 __ATTR_RW_MODE(type, 0600);
449 static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr =
450 __ATTR_RW_MODE(matching, 0600);
452 static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr =
453 __ATTR_RW_MODE(memcg_path, 0600);
455 static struct kobj_attribute damon_sysfs_scheme_filter_addr_start_attr =
456 __ATTR_RW_MODE(addr_start, 0600);
458 static struct kobj_attribute damon_sysfs_scheme_filter_addr_end_attr =
459 __ATTR_RW_MODE(addr_end, 0600);
461 static struct kobj_attribute damon_sysfs_scheme_filter_damon_target_idx_attr =
462 __ATTR_RW_MODE(damon_target_idx, 0600);
464 static struct attribute *damon_sysfs_scheme_filter_attrs[] = {
465 &damon_sysfs_scheme_filter_type_attr.attr,
466 &damon_sysfs_scheme_filter_matching_attr.attr,
467 &damon_sysfs_scheme_filter_memcg_path_attr.attr,
468 &damon_sysfs_scheme_filter_addr_start_attr.attr,
469 &damon_sysfs_scheme_filter_addr_end_attr.attr,
470 &damon_sysfs_scheme_filter_damon_target_idx_attr.attr,
473 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter);
475 static const struct kobj_type damon_sysfs_scheme_filter_ktype = {
476 .release = damon_sysfs_scheme_filter_release,
477 .sysfs_ops = &kobj_sysfs_ops,
478 .default_groups = damon_sysfs_scheme_filter_groups,
485 struct damon_sysfs_scheme_filters {
487 struct damon_sysfs_scheme_filter **filters_arr;
491 static struct damon_sysfs_scheme_filters *
492 damon_sysfs_scheme_filters_alloc(void)
494 return kzalloc(sizeof(struct damon_sysfs_scheme_filters), GFP_KERNEL);
497 static void damon_sysfs_scheme_filters_rm_dirs(
498 struct damon_sysfs_scheme_filters *filters)
500 struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr;
503 for (i = 0; i < filters->nr; i++)
504 kobject_put(&filters_arr[i]->kobj);
507 filters->filters_arr = NULL;
510 static int damon_sysfs_scheme_filters_add_dirs(
511 struct damon_sysfs_scheme_filters *filters, int nr_filters)
513 struct damon_sysfs_scheme_filter **filters_arr, *filter;
516 damon_sysfs_scheme_filters_rm_dirs(filters);
520 filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr),
521 GFP_KERNEL | __GFP_NOWARN);
524 filters->filters_arr = filters_arr;
526 for (i = 0; i < nr_filters; i++) {
527 filter = damon_sysfs_scheme_filter_alloc();
529 damon_sysfs_scheme_filters_rm_dirs(filters);
533 err = kobject_init_and_add(&filter->kobj,
534 &damon_sysfs_scheme_filter_ktype,
535 &filters->kobj, "%d", i);
537 kobject_put(&filter->kobj);
538 damon_sysfs_scheme_filters_rm_dirs(filters);
542 filters_arr[i] = filter;
548 static ssize_t nr_filters_show(struct kobject *kobj,
549 struct kobj_attribute *attr, char *buf)
551 struct damon_sysfs_scheme_filters *filters = container_of(kobj,
552 struct damon_sysfs_scheme_filters, kobj);
554 return sysfs_emit(buf, "%d\n", filters->nr);
557 static ssize_t nr_filters_store(struct kobject *kobj,
558 struct kobj_attribute *attr, const char *buf, size_t count)
560 struct damon_sysfs_scheme_filters *filters;
561 int nr, err = kstrtoint(buf, 0, &nr);
568 filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj);
570 if (!mutex_trylock(&damon_sysfs_lock))
572 err = damon_sysfs_scheme_filters_add_dirs(filters, nr);
573 mutex_unlock(&damon_sysfs_lock);
580 static void damon_sysfs_scheme_filters_release(struct kobject *kobj)
582 kfree(container_of(kobj, struct damon_sysfs_scheme_filters, kobj));
585 static struct kobj_attribute damon_sysfs_scheme_filters_nr_attr =
586 __ATTR_RW_MODE(nr_filters, 0600);
588 static struct attribute *damon_sysfs_scheme_filters_attrs[] = {
589 &damon_sysfs_scheme_filters_nr_attr.attr,
592 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filters);
594 static const struct kobj_type damon_sysfs_scheme_filters_ktype = {
595 .release = damon_sysfs_scheme_filters_release,
596 .sysfs_ops = &kobj_sysfs_ops,
597 .default_groups = damon_sysfs_scheme_filters_groups,
601 * watermarks directory
604 struct damon_sysfs_watermarks {
606 enum damos_wmark_metric metric;
607 unsigned long interval_us;
613 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
614 enum damos_wmark_metric metric, unsigned long interval_us,
615 unsigned long high, unsigned long mid, unsigned long low)
617 struct damon_sysfs_watermarks *watermarks = kmalloc(
618 sizeof(*watermarks), GFP_KERNEL);
622 watermarks->kobj = (struct kobject){};
623 watermarks->metric = metric;
624 watermarks->interval_us = interval_us;
625 watermarks->high = high;
626 watermarks->mid = mid;
627 watermarks->low = low;
631 /* Should match with enum damos_wmark_metric */
632 static const char * const damon_sysfs_wmark_metric_strs[] = {
637 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
640 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
641 struct damon_sysfs_watermarks, kobj);
643 return sysfs_emit(buf, "%s\n",
644 damon_sysfs_wmark_metric_strs[watermarks->metric]);
647 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
648 const char *buf, size_t count)
650 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
651 struct damon_sysfs_watermarks, kobj);
652 enum damos_wmark_metric metric;
654 for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) {
655 if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) {
656 watermarks->metric = metric;
663 static ssize_t interval_us_show(struct kobject *kobj,
664 struct kobj_attribute *attr, char *buf)
666 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
667 struct damon_sysfs_watermarks, kobj);
669 return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
672 static ssize_t interval_us_store(struct kobject *kobj,
673 struct kobj_attribute *attr, const char *buf, size_t count)
675 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
676 struct damon_sysfs_watermarks, kobj);
677 int err = kstrtoul(buf, 0, &watermarks->interval_us);
679 return err ? err : count;
682 static ssize_t high_show(struct kobject *kobj,
683 struct kobj_attribute *attr, char *buf)
685 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
686 struct damon_sysfs_watermarks, kobj);
688 return sysfs_emit(buf, "%lu\n", watermarks->high);
691 static ssize_t high_store(struct kobject *kobj,
692 struct kobj_attribute *attr, const char *buf, size_t count)
694 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
695 struct damon_sysfs_watermarks, kobj);
696 int err = kstrtoul(buf, 0, &watermarks->high);
698 return err ? err : count;
701 static ssize_t mid_show(struct kobject *kobj,
702 struct kobj_attribute *attr, char *buf)
704 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
705 struct damon_sysfs_watermarks, kobj);
707 return sysfs_emit(buf, "%lu\n", watermarks->mid);
710 static ssize_t mid_store(struct kobject *kobj,
711 struct kobj_attribute *attr, const char *buf, size_t count)
713 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
714 struct damon_sysfs_watermarks, kobj);
715 int err = kstrtoul(buf, 0, &watermarks->mid);
717 return err ? err : count;
720 static ssize_t low_show(struct kobject *kobj,
721 struct kobj_attribute *attr, char *buf)
723 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
724 struct damon_sysfs_watermarks, kobj);
726 return sysfs_emit(buf, "%lu\n", watermarks->low);
729 static ssize_t low_store(struct kobject *kobj,
730 struct kobj_attribute *attr, const char *buf, size_t count)
732 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
733 struct damon_sysfs_watermarks, kobj);
734 int err = kstrtoul(buf, 0, &watermarks->low);
736 return err ? err : count;
739 static void damon_sysfs_watermarks_release(struct kobject *kobj)
741 kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
744 static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
745 __ATTR_RW_MODE(metric, 0600);
747 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
748 __ATTR_RW_MODE(interval_us, 0600);
750 static struct kobj_attribute damon_sysfs_watermarks_high_attr =
751 __ATTR_RW_MODE(high, 0600);
753 static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
754 __ATTR_RW_MODE(mid, 0600);
756 static struct kobj_attribute damon_sysfs_watermarks_low_attr =
757 __ATTR_RW_MODE(low, 0600);
759 static struct attribute *damon_sysfs_watermarks_attrs[] = {
760 &damon_sysfs_watermarks_metric_attr.attr,
761 &damon_sysfs_watermarks_interval_us_attr.attr,
762 &damon_sysfs_watermarks_high_attr.attr,
763 &damon_sysfs_watermarks_mid_attr.attr,
764 &damon_sysfs_watermarks_low_attr.attr,
767 ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
769 static const struct kobj_type damon_sysfs_watermarks_ktype = {
770 .release = damon_sysfs_watermarks_release,
771 .sysfs_ops = &kobj_sysfs_ops,
772 .default_groups = damon_sysfs_watermarks_groups,
776 * scheme/weights directory
779 struct damon_sysfs_weights {
782 unsigned int nr_accesses;
786 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
787 unsigned int nr_accesses, unsigned int age)
789 struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
794 weights->kobj = (struct kobject){};
796 weights->nr_accesses = nr_accesses;
801 static ssize_t sz_permil_show(struct kobject *kobj,
802 struct kobj_attribute *attr, char *buf)
804 struct damon_sysfs_weights *weights = container_of(kobj,
805 struct damon_sysfs_weights, kobj);
807 return sysfs_emit(buf, "%u\n", weights->sz);
810 static ssize_t sz_permil_store(struct kobject *kobj,
811 struct kobj_attribute *attr, const char *buf, size_t count)
813 struct damon_sysfs_weights *weights = container_of(kobj,
814 struct damon_sysfs_weights, kobj);
815 int err = kstrtouint(buf, 0, &weights->sz);
817 return err ? err : count;
820 static ssize_t nr_accesses_permil_show(struct kobject *kobj,
821 struct kobj_attribute *attr, char *buf)
823 struct damon_sysfs_weights *weights = container_of(kobj,
824 struct damon_sysfs_weights, kobj);
826 return sysfs_emit(buf, "%u\n", weights->nr_accesses);
829 static ssize_t nr_accesses_permil_store(struct kobject *kobj,
830 struct kobj_attribute *attr, const char *buf, size_t count)
832 struct damon_sysfs_weights *weights = container_of(kobj,
833 struct damon_sysfs_weights, kobj);
834 int err = kstrtouint(buf, 0, &weights->nr_accesses);
836 return err ? err : count;
839 static ssize_t age_permil_show(struct kobject *kobj,
840 struct kobj_attribute *attr, char *buf)
842 struct damon_sysfs_weights *weights = container_of(kobj,
843 struct damon_sysfs_weights, kobj);
845 return sysfs_emit(buf, "%u\n", weights->age);
848 static ssize_t age_permil_store(struct kobject *kobj,
849 struct kobj_attribute *attr, const char *buf, size_t count)
851 struct damon_sysfs_weights *weights = container_of(kobj,
852 struct damon_sysfs_weights, kobj);
853 int err = kstrtouint(buf, 0, &weights->age);
855 return err ? err : count;
858 static void damon_sysfs_weights_release(struct kobject *kobj)
860 kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
863 static struct kobj_attribute damon_sysfs_weights_sz_attr =
864 __ATTR_RW_MODE(sz_permil, 0600);
866 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
867 __ATTR_RW_MODE(nr_accesses_permil, 0600);
869 static struct kobj_attribute damon_sysfs_weights_age_attr =
870 __ATTR_RW_MODE(age_permil, 0600);
872 static struct attribute *damon_sysfs_weights_attrs[] = {
873 &damon_sysfs_weights_sz_attr.attr,
874 &damon_sysfs_weights_nr_accesses_attr.attr,
875 &damon_sysfs_weights_age_attr.attr,
878 ATTRIBUTE_GROUPS(damon_sysfs_weights);
880 static const struct kobj_type damon_sysfs_weights_ktype = {
881 .release = damon_sysfs_weights_release,
882 .sysfs_ops = &kobj_sysfs_ops,
883 .default_groups = damon_sysfs_weights_groups,
890 struct damon_sysfs_quotas {
892 struct damon_sysfs_weights *weights;
895 unsigned long reset_interval_ms;
898 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
900 return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
903 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
905 struct damon_sysfs_weights *weights;
908 weights = damon_sysfs_weights_alloc(0, 0, 0);
912 err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
913 "as->kobj, "weights");
915 kobject_put(&weights->kobj);
917 quotas->weights = weights;
921 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
923 kobject_put("as->weights->kobj);
926 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
929 struct damon_sysfs_quotas *quotas = container_of(kobj,
930 struct damon_sysfs_quotas, kobj);
932 return sysfs_emit(buf, "%lu\n", quotas->ms);
935 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
936 const char *buf, size_t count)
938 struct damon_sysfs_quotas *quotas = container_of(kobj,
939 struct damon_sysfs_quotas, kobj);
940 int err = kstrtoul(buf, 0, "as->ms);
947 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
950 struct damon_sysfs_quotas *quotas = container_of(kobj,
951 struct damon_sysfs_quotas, kobj);
953 return sysfs_emit(buf, "%lu\n", quotas->sz);
956 static ssize_t bytes_store(struct kobject *kobj,
957 struct kobj_attribute *attr, const char *buf, size_t count)
959 struct damon_sysfs_quotas *quotas = container_of(kobj,
960 struct damon_sysfs_quotas, kobj);
961 int err = kstrtoul(buf, 0, "as->sz);
968 static ssize_t reset_interval_ms_show(struct kobject *kobj,
969 struct kobj_attribute *attr, char *buf)
971 struct damon_sysfs_quotas *quotas = container_of(kobj,
972 struct damon_sysfs_quotas, kobj);
974 return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
977 static ssize_t reset_interval_ms_store(struct kobject *kobj,
978 struct kobj_attribute *attr, const char *buf, size_t count)
980 struct damon_sysfs_quotas *quotas = container_of(kobj,
981 struct damon_sysfs_quotas, kobj);
982 int err = kstrtoul(buf, 0, "as->reset_interval_ms);
989 static void damon_sysfs_quotas_release(struct kobject *kobj)
991 kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
994 static struct kobj_attribute damon_sysfs_quotas_ms_attr =
995 __ATTR_RW_MODE(ms, 0600);
997 static struct kobj_attribute damon_sysfs_quotas_sz_attr =
998 __ATTR_RW_MODE(bytes, 0600);
1000 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
1001 __ATTR_RW_MODE(reset_interval_ms, 0600);
1003 static struct attribute *damon_sysfs_quotas_attrs[] = {
1004 &damon_sysfs_quotas_ms_attr.attr,
1005 &damon_sysfs_quotas_sz_attr.attr,
1006 &damon_sysfs_quotas_reset_interval_ms_attr.attr,
1009 ATTRIBUTE_GROUPS(damon_sysfs_quotas);
1011 static const struct kobj_type damon_sysfs_quotas_ktype = {
1012 .release = damon_sysfs_quotas_release,
1013 .sysfs_ops = &kobj_sysfs_ops,
1014 .default_groups = damon_sysfs_quotas_groups,
1018 * access_pattern directory
1021 struct damon_sysfs_access_pattern {
1022 struct kobject kobj;
1023 struct damon_sysfs_ul_range *sz;
1024 struct damon_sysfs_ul_range *nr_accesses;
1025 struct damon_sysfs_ul_range *age;
1029 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void)
1031 struct damon_sysfs_access_pattern *access_pattern =
1032 kmalloc(sizeof(*access_pattern), GFP_KERNEL);
1034 if (!access_pattern)
1036 access_pattern->kobj = (struct kobject){};
1037 return access_pattern;
1040 static int damon_sysfs_access_pattern_add_range_dir(
1041 struct damon_sysfs_access_pattern *access_pattern,
1042 struct damon_sysfs_ul_range **range_dir_ptr,
1045 struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0);
1050 err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype,
1051 &access_pattern->kobj, name);
1053 kobject_put(&range->kobj);
1055 *range_dir_ptr = range;
1059 static int damon_sysfs_access_pattern_add_dirs(
1060 struct damon_sysfs_access_pattern *access_pattern)
1064 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1065 &access_pattern->sz, "sz");
1069 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1070 &access_pattern->nr_accesses, "nr_accesses");
1072 goto put_nr_accesses_sz_out;
1074 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1075 &access_pattern->age, "age");
1077 goto put_age_nr_accesses_sz_out;
1080 put_age_nr_accesses_sz_out:
1081 kobject_put(&access_pattern->age->kobj);
1082 access_pattern->age = NULL;
1083 put_nr_accesses_sz_out:
1084 kobject_put(&access_pattern->nr_accesses->kobj);
1085 access_pattern->nr_accesses = NULL;
1087 kobject_put(&access_pattern->sz->kobj);
1088 access_pattern->sz = NULL;
1092 static void damon_sysfs_access_pattern_rm_dirs(
1093 struct damon_sysfs_access_pattern *access_pattern)
1095 kobject_put(&access_pattern->sz->kobj);
1096 kobject_put(&access_pattern->nr_accesses->kobj);
1097 kobject_put(&access_pattern->age->kobj);
1100 static void damon_sysfs_access_pattern_release(struct kobject *kobj)
1102 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj));
1105 static struct attribute *damon_sysfs_access_pattern_attrs[] = {
1108 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern);
1110 static const struct kobj_type damon_sysfs_access_pattern_ktype = {
1111 .release = damon_sysfs_access_pattern_release,
1112 .sysfs_ops = &kobj_sysfs_ops,
1113 .default_groups = damon_sysfs_access_pattern_groups,
1120 struct damon_sysfs_scheme {
1121 struct kobject kobj;
1122 enum damos_action action;
1123 struct damon_sysfs_access_pattern *access_pattern;
1124 struct damon_sysfs_quotas *quotas;
1125 struct damon_sysfs_watermarks *watermarks;
1126 struct damon_sysfs_scheme_filters *filters;
1127 struct damon_sysfs_stats *stats;
1128 struct damon_sysfs_scheme_regions *tried_regions;
1131 /* This should match with enum damos_action */
1132 static const char * const damon_sysfs_damos_action_strs[] = {
1143 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
1144 enum damos_action action)
1146 struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme),
1151 scheme->kobj = (struct kobject){};
1152 scheme->action = action;
1156 static int damon_sysfs_scheme_set_access_pattern(
1157 struct damon_sysfs_scheme *scheme)
1159 struct damon_sysfs_access_pattern *access_pattern;
1162 access_pattern = damon_sysfs_access_pattern_alloc();
1163 if (!access_pattern)
1165 err = kobject_init_and_add(&access_pattern->kobj,
1166 &damon_sysfs_access_pattern_ktype, &scheme->kobj,
1170 err = damon_sysfs_access_pattern_add_dirs(access_pattern);
1173 scheme->access_pattern = access_pattern;
1177 kobject_put(&access_pattern->kobj);
1181 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
1183 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
1188 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype,
1189 &scheme->kobj, "quotas");
1192 err = damon_sysfs_quotas_add_dirs(quotas);
1195 scheme->quotas = quotas;
1199 kobject_put("as->kobj);
1203 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
1205 struct damon_sysfs_watermarks *watermarks =
1206 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
1211 err = kobject_init_and_add(&watermarks->kobj,
1212 &damon_sysfs_watermarks_ktype, &scheme->kobj,
1215 kobject_put(&watermarks->kobj);
1217 scheme->watermarks = watermarks;
1221 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme)
1223 struct damon_sysfs_scheme_filters *filters =
1224 damon_sysfs_scheme_filters_alloc();
1229 err = kobject_init_and_add(&filters->kobj,
1230 &damon_sysfs_scheme_filters_ktype, &scheme->kobj,
1233 kobject_put(&filters->kobj);
1235 scheme->filters = filters;
1239 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme)
1241 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc();
1246 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype,
1247 &scheme->kobj, "stats");
1249 kobject_put(&stats->kobj);
1251 scheme->stats = stats;
1255 static int damon_sysfs_scheme_set_tried_regions(
1256 struct damon_sysfs_scheme *scheme)
1258 struct damon_sysfs_scheme_regions *tried_regions =
1259 damon_sysfs_scheme_regions_alloc();
1264 err = kobject_init_and_add(&tried_regions->kobj,
1265 &damon_sysfs_scheme_regions_ktype, &scheme->kobj,
1268 kobject_put(&tried_regions->kobj);
1270 scheme->tried_regions = tried_regions;
1274 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
1278 err = damon_sysfs_scheme_set_access_pattern(scheme);
1281 err = damon_sysfs_scheme_set_quotas(scheme);
1283 goto put_access_pattern_out;
1284 err = damon_sysfs_scheme_set_watermarks(scheme);
1286 goto put_quotas_access_pattern_out;
1287 err = damon_sysfs_scheme_set_filters(scheme);
1289 goto put_watermarks_quotas_access_pattern_out;
1290 err = damon_sysfs_scheme_set_stats(scheme);
1292 goto put_filters_watermarks_quotas_access_pattern_out;
1293 err = damon_sysfs_scheme_set_tried_regions(scheme);
1295 goto put_tried_regions_out;
1298 put_tried_regions_out:
1299 kobject_put(&scheme->tried_regions->kobj);
1300 scheme->tried_regions = NULL;
1301 put_filters_watermarks_quotas_access_pattern_out:
1302 kobject_put(&scheme->filters->kobj);
1303 scheme->filters = NULL;
1304 put_watermarks_quotas_access_pattern_out:
1305 kobject_put(&scheme->watermarks->kobj);
1306 scheme->watermarks = NULL;
1307 put_quotas_access_pattern_out:
1308 kobject_put(&scheme->quotas->kobj);
1309 scheme->quotas = NULL;
1310 put_access_pattern_out:
1311 kobject_put(&scheme->access_pattern->kobj);
1312 scheme->access_pattern = NULL;
1316 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
1318 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
1319 kobject_put(&scheme->access_pattern->kobj);
1320 damon_sysfs_quotas_rm_dirs(scheme->quotas);
1321 kobject_put(&scheme->quotas->kobj);
1322 kobject_put(&scheme->watermarks->kobj);
1323 damon_sysfs_scheme_filters_rm_dirs(scheme->filters);
1324 kobject_put(&scheme->filters->kobj);
1325 kobject_put(&scheme->stats->kobj);
1326 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions);
1327 kobject_put(&scheme->tried_regions->kobj);
1330 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
1333 struct damon_sysfs_scheme *scheme = container_of(kobj,
1334 struct damon_sysfs_scheme, kobj);
1336 return sysfs_emit(buf, "%s\n",
1337 damon_sysfs_damos_action_strs[scheme->action]);
1340 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr,
1341 const char *buf, size_t count)
1343 struct damon_sysfs_scheme *scheme = container_of(kobj,
1344 struct damon_sysfs_scheme, kobj);
1345 enum damos_action action;
1347 for (action = 0; action < NR_DAMOS_ACTIONS; action++) {
1348 if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) {
1349 scheme->action = action;
1356 static void damon_sysfs_scheme_release(struct kobject *kobj)
1358 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
1361 static struct kobj_attribute damon_sysfs_scheme_action_attr =
1362 __ATTR_RW_MODE(action, 0600);
1364 static struct attribute *damon_sysfs_scheme_attrs[] = {
1365 &damon_sysfs_scheme_action_attr.attr,
1368 ATTRIBUTE_GROUPS(damon_sysfs_scheme);
1370 static const struct kobj_type damon_sysfs_scheme_ktype = {
1371 .release = damon_sysfs_scheme_release,
1372 .sysfs_ops = &kobj_sysfs_ops,
1373 .default_groups = damon_sysfs_scheme_groups,
1380 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void)
1382 return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL);
1385 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes)
1387 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr;
1390 for (i = 0; i < schemes->nr; i++) {
1391 damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
1392 kobject_put(&schemes_arr[i]->kobj);
1396 schemes->schemes_arr = NULL;
1399 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes,
1402 struct damon_sysfs_scheme **schemes_arr, *scheme;
1405 damon_sysfs_schemes_rm_dirs(schemes);
1409 schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr),
1410 GFP_KERNEL | __GFP_NOWARN);
1413 schemes->schemes_arr = schemes_arr;
1415 for (i = 0; i < nr_schemes; i++) {
1416 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT);
1418 damon_sysfs_schemes_rm_dirs(schemes);
1422 err = kobject_init_and_add(&scheme->kobj,
1423 &damon_sysfs_scheme_ktype, &schemes->kobj,
1427 err = damon_sysfs_scheme_add_dirs(scheme);
1431 schemes_arr[i] = scheme;
1437 damon_sysfs_schemes_rm_dirs(schemes);
1438 kobject_put(&scheme->kobj);
1442 static ssize_t nr_schemes_show(struct kobject *kobj,
1443 struct kobj_attribute *attr, char *buf)
1445 struct damon_sysfs_schemes *schemes = container_of(kobj,
1446 struct damon_sysfs_schemes, kobj);
1448 return sysfs_emit(buf, "%d\n", schemes->nr);
1451 static ssize_t nr_schemes_store(struct kobject *kobj,
1452 struct kobj_attribute *attr, const char *buf, size_t count)
1454 struct damon_sysfs_schemes *schemes;
1455 int nr, err = kstrtoint(buf, 0, &nr);
1462 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj);
1464 if (!mutex_trylock(&damon_sysfs_lock))
1466 err = damon_sysfs_schemes_add_dirs(schemes, nr);
1467 mutex_unlock(&damon_sysfs_lock);
1473 static void damon_sysfs_schemes_release(struct kobject *kobj)
1475 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj));
1478 static struct kobj_attribute damon_sysfs_schemes_nr_attr =
1479 __ATTR_RW_MODE(nr_schemes, 0600);
1481 static struct attribute *damon_sysfs_schemes_attrs[] = {
1482 &damon_sysfs_schemes_nr_attr.attr,
1485 ATTRIBUTE_GROUPS(damon_sysfs_schemes);
1487 const struct kobj_type damon_sysfs_schemes_ktype = {
1488 .release = damon_sysfs_schemes_release,
1489 .sysfs_ops = &kobj_sysfs_ops,
1490 .default_groups = damon_sysfs_schemes_groups,
1493 static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg,
1494 char *memcg_path_buf, char *path)
1497 cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX);
1498 if (sysfs_streq(memcg_path_buf, path))
1500 #endif /* CONFIG_MEMCG */
1504 static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id)
1506 struct mem_cgroup *memcg;
1513 path = kmalloc(sizeof(*path) * PATH_MAX, GFP_KERNEL);
1517 for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg;
1518 memcg = mem_cgroup_iter(NULL, memcg, NULL)) {
1519 /* skip removed memcg */
1520 if (!mem_cgroup_id(memcg))
1522 if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) {
1523 *id = mem_cgroup_id(memcg);
1530 return found ? 0 : -EINVAL;
1533 static int damon_sysfs_set_scheme_filters(struct damos *scheme,
1534 struct damon_sysfs_scheme_filters *sysfs_filters)
1537 struct damos_filter *filter, *next;
1539 damos_for_each_filter_safe(filter, next, scheme)
1540 damos_destroy_filter(filter);
1542 for (i = 0; i < sysfs_filters->nr; i++) {
1543 struct damon_sysfs_scheme_filter *sysfs_filter =
1544 sysfs_filters->filters_arr[i];
1545 struct damos_filter *filter =
1546 damos_new_filter(sysfs_filter->type,
1547 sysfs_filter->matching);
1552 if (filter->type == DAMOS_FILTER_TYPE_MEMCG) {
1553 err = damon_sysfs_memcg_path_to_id(
1554 sysfs_filter->memcg_path,
1557 damos_destroy_filter(filter);
1560 } else if (filter->type == DAMOS_FILTER_TYPE_ADDR) {
1561 if (sysfs_filter->addr_range.end <
1562 sysfs_filter->addr_range.start) {
1563 damos_destroy_filter(filter);
1566 filter->addr_range = sysfs_filter->addr_range;
1567 } else if (filter->type == DAMOS_FILTER_TYPE_TARGET) {
1568 filter->target_idx = sysfs_filter->target_idx;
1571 damos_add_filter(scheme, filter);
1576 static struct damos *damon_sysfs_mk_scheme(
1577 struct damon_sysfs_scheme *sysfs_scheme)
1579 struct damon_sysfs_access_pattern *access_pattern =
1580 sysfs_scheme->access_pattern;
1581 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1582 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1583 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1584 struct damon_sysfs_scheme_filters *sysfs_filters =
1585 sysfs_scheme->filters;
1586 struct damos *scheme;
1589 struct damos_access_pattern pattern = {
1590 .min_sz_region = access_pattern->sz->min,
1591 .max_sz_region = access_pattern->sz->max,
1592 .min_nr_accesses = access_pattern->nr_accesses->min,
1593 .max_nr_accesses = access_pattern->nr_accesses->max,
1594 .min_age_region = access_pattern->age->min,
1595 .max_age_region = access_pattern->age->max,
1597 struct damos_quota quota = {
1598 .ms = sysfs_quotas->ms,
1599 .sz = sysfs_quotas->sz,
1600 .reset_interval = sysfs_quotas->reset_interval_ms,
1601 .weight_sz = sysfs_weights->sz,
1602 .weight_nr_accesses = sysfs_weights->nr_accesses,
1603 .weight_age = sysfs_weights->age,
1605 struct damos_watermarks wmarks = {
1606 .metric = sysfs_wmarks->metric,
1607 .interval = sysfs_wmarks->interval_us,
1608 .high = sysfs_wmarks->high,
1609 .mid = sysfs_wmarks->mid,
1610 .low = sysfs_wmarks->low,
1613 scheme = damon_new_scheme(&pattern, sysfs_scheme->action, "a,
1618 err = damon_sysfs_set_scheme_filters(scheme, sysfs_filters);
1620 damon_destroy_scheme(scheme);
1626 static void damon_sysfs_update_scheme(struct damos *scheme,
1627 struct damon_sysfs_scheme *sysfs_scheme)
1629 struct damon_sysfs_access_pattern *access_pattern =
1630 sysfs_scheme->access_pattern;
1631 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1632 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1633 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1636 scheme->pattern.min_sz_region = access_pattern->sz->min;
1637 scheme->pattern.max_sz_region = access_pattern->sz->max;
1638 scheme->pattern.min_nr_accesses = access_pattern->nr_accesses->min;
1639 scheme->pattern.max_nr_accesses = access_pattern->nr_accesses->max;
1640 scheme->pattern.min_age_region = access_pattern->age->min;
1641 scheme->pattern.max_age_region = access_pattern->age->max;
1643 scheme->action = sysfs_scheme->action;
1645 scheme->quota.ms = sysfs_quotas->ms;
1646 scheme->quota.sz = sysfs_quotas->sz;
1647 scheme->quota.reset_interval = sysfs_quotas->reset_interval_ms;
1648 scheme->quota.weight_sz = sysfs_weights->sz;
1649 scheme->quota.weight_nr_accesses = sysfs_weights->nr_accesses;
1650 scheme->quota.weight_age = sysfs_weights->age;
1652 scheme->wmarks.metric = sysfs_wmarks->metric;
1653 scheme->wmarks.interval = sysfs_wmarks->interval_us;
1654 scheme->wmarks.high = sysfs_wmarks->high;
1655 scheme->wmarks.mid = sysfs_wmarks->mid;
1656 scheme->wmarks.low = sysfs_wmarks->low;
1658 err = damon_sysfs_set_scheme_filters(scheme, sysfs_scheme->filters);
1660 damon_destroy_scheme(scheme);
1663 int damon_sysfs_set_schemes(struct damon_ctx *ctx,
1664 struct damon_sysfs_schemes *sysfs_schemes)
1666 struct damos *scheme, *next;
1669 damon_for_each_scheme_safe(scheme, next, ctx) {
1670 if (i < sysfs_schemes->nr)
1671 damon_sysfs_update_scheme(scheme,
1672 sysfs_schemes->schemes_arr[i]);
1674 damon_destroy_scheme(scheme);
1678 for (; i < sysfs_schemes->nr; i++) {
1679 struct damos *scheme, *next;
1681 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]);
1683 damon_for_each_scheme_safe(scheme, next, ctx)
1684 damon_destroy_scheme(scheme);
1687 damon_add_scheme(ctx, scheme);
1692 void damon_sysfs_schemes_update_stats(
1693 struct damon_sysfs_schemes *sysfs_schemes,
1694 struct damon_ctx *ctx)
1696 struct damos *scheme;
1697 int schemes_idx = 0;
1699 damon_for_each_scheme(scheme, ctx) {
1700 struct damon_sysfs_stats *sysfs_stats;
1702 /* user could have removed the scheme sysfs dir */
1703 if (schemes_idx >= sysfs_schemes->nr)
1706 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats;
1707 sysfs_stats->nr_tried = scheme->stat.nr_tried;
1708 sysfs_stats->sz_tried = scheme->stat.sz_tried;
1709 sysfs_stats->nr_applied = scheme->stat.nr_applied;
1710 sysfs_stats->sz_applied = scheme->stat.sz_applied;
1711 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds;
1716 * damon_sysfs_schemes that need to update its schemes regions dir. Protected
1717 * by damon_sysfs_lock
1719 static struct damon_sysfs_schemes *damon_sysfs_schemes_for_damos_callback;
1720 static int damon_sysfs_schemes_region_idx;
1721 static bool damos_regions_upd_total_bytes_only;
1724 * DAMON callback that called before damos apply. While this callback is
1725 * registered, damon_sysfs_lock should be held to ensure the regions
1726 * directories exist.
1728 static int damon_sysfs_before_damos_apply(struct damon_ctx *ctx,
1729 struct damon_target *t, struct damon_region *r,
1732 struct damos *scheme;
1733 struct damon_sysfs_scheme_regions *sysfs_regions;
1734 struct damon_sysfs_scheme_region *region;
1735 struct damon_sysfs_schemes *sysfs_schemes =
1736 damon_sysfs_schemes_for_damos_callback;
1737 int schemes_idx = 0;
1739 damon_for_each_scheme(scheme, ctx) {
1745 /* user could have removed the scheme sysfs dir */
1746 if (schemes_idx >= sysfs_schemes->nr)
1749 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions;
1750 sysfs_regions->total_bytes += r->ar.end - r->ar.start;
1751 if (damos_regions_upd_total_bytes_only)
1754 region = damon_sysfs_scheme_region_alloc(r);
1755 list_add_tail(®ion->list, &sysfs_regions->regions_list);
1756 sysfs_regions->nr_regions++;
1757 if (kobject_init_and_add(®ion->kobj,
1758 &damon_sysfs_scheme_region_ktype,
1759 &sysfs_regions->kobj, "%d",
1760 damon_sysfs_schemes_region_idx++)) {
1761 kobject_put(®ion->kobj);
1766 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1767 int damon_sysfs_schemes_clear_regions(
1768 struct damon_sysfs_schemes *sysfs_schemes,
1769 struct damon_ctx *ctx)
1771 struct damos *scheme;
1772 int schemes_idx = 0;
1774 damon_for_each_scheme(scheme, ctx) {
1775 struct damon_sysfs_scheme *sysfs_scheme;
1777 /* user could have removed the scheme sysfs dir */
1778 if (schemes_idx >= sysfs_schemes->nr)
1781 sysfs_scheme = sysfs_schemes->schemes_arr[schemes_idx++];
1782 damon_sysfs_scheme_regions_rm_dirs(
1783 sysfs_scheme->tried_regions);
1784 sysfs_scheme->tried_regions->total_bytes = 0;
1789 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1790 int damon_sysfs_schemes_update_regions_start(
1791 struct damon_sysfs_schemes *sysfs_schemes,
1792 struct damon_ctx *ctx, bool total_bytes_only)
1794 damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx);
1795 damon_sysfs_schemes_for_damos_callback = sysfs_schemes;
1796 damos_regions_upd_total_bytes_only = total_bytes_only;
1797 ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply;
1802 * Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock. Caller
1803 * should unlock damon_sysfs_lock which held before
1804 * damon_sysfs_schemes_update_regions_start()
1806 int damon_sysfs_schemes_update_regions_stop(struct damon_ctx *ctx)
1808 damon_sysfs_schemes_for_damos_callback = NULL;
1809 ctx->callback.before_damos_apply = NULL;
1810 damon_sysfs_schemes_region_idx = 0;