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 struct kobj_type damon_sysfs_scheme_region_ktype = {
107 .release = damon_sysfs_scheme_region_release,
108 .sysfs_ops = &kobj_sysfs_ops,
109 .default_groups = damon_sysfs_scheme_region_groups,
113 * scheme regions directory
116 struct damon_sysfs_scheme_regions {
118 struct list_head regions_list;
122 static struct damon_sysfs_scheme_regions *
123 damon_sysfs_scheme_regions_alloc(void)
125 struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions),
128 regions->kobj = (struct kobject){};
129 INIT_LIST_HEAD(®ions->regions_list);
130 regions->nr_regions = 0;
134 static void damon_sysfs_scheme_regions_rm_dirs(
135 struct damon_sysfs_scheme_regions *regions)
137 struct damon_sysfs_scheme_region *r, *next;
139 list_for_each_entry_safe(r, next, ®ions->regions_list, list) {
140 /* release function deletes it from the list */
141 kobject_put(&r->kobj);
142 regions->nr_regions--;
146 static void damon_sysfs_scheme_regions_release(struct kobject *kobj)
148 kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj));
151 static struct attribute *damon_sysfs_scheme_regions_attrs[] = {
154 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions);
156 static struct kobj_type damon_sysfs_scheme_regions_ktype = {
157 .release = damon_sysfs_scheme_regions_release,
158 .sysfs_ops = &kobj_sysfs_ops,
159 .default_groups = damon_sysfs_scheme_regions_groups,
163 * schemes/stats directory
166 struct damon_sysfs_stats {
168 unsigned long nr_tried;
169 unsigned long sz_tried;
170 unsigned long nr_applied;
171 unsigned long sz_applied;
172 unsigned long qt_exceeds;
175 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void)
177 return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL);
180 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
183 struct damon_sysfs_stats *stats = container_of(kobj,
184 struct damon_sysfs_stats, kobj);
186 return sysfs_emit(buf, "%lu\n", stats->nr_tried);
189 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
192 struct damon_sysfs_stats *stats = container_of(kobj,
193 struct damon_sysfs_stats, kobj);
195 return sysfs_emit(buf, "%lu\n", stats->sz_tried);
198 static ssize_t nr_applied_show(struct kobject *kobj,
199 struct kobj_attribute *attr, char *buf)
201 struct damon_sysfs_stats *stats = container_of(kobj,
202 struct damon_sysfs_stats, kobj);
204 return sysfs_emit(buf, "%lu\n", stats->nr_applied);
207 static ssize_t sz_applied_show(struct kobject *kobj,
208 struct kobj_attribute *attr, char *buf)
210 struct damon_sysfs_stats *stats = container_of(kobj,
211 struct damon_sysfs_stats, kobj);
213 return sysfs_emit(buf, "%lu\n", stats->sz_applied);
216 static ssize_t qt_exceeds_show(struct kobject *kobj,
217 struct kobj_attribute *attr, char *buf)
219 struct damon_sysfs_stats *stats = container_of(kobj,
220 struct damon_sysfs_stats, kobj);
222 return sysfs_emit(buf, "%lu\n", stats->qt_exceeds);
225 static void damon_sysfs_stats_release(struct kobject *kobj)
227 kfree(container_of(kobj, struct damon_sysfs_stats, kobj));
230 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr =
231 __ATTR_RO_MODE(nr_tried, 0400);
233 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr =
234 __ATTR_RO_MODE(sz_tried, 0400);
236 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr =
237 __ATTR_RO_MODE(nr_applied, 0400);
239 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr =
240 __ATTR_RO_MODE(sz_applied, 0400);
242 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr =
243 __ATTR_RO_MODE(qt_exceeds, 0400);
245 static struct attribute *damon_sysfs_stats_attrs[] = {
246 &damon_sysfs_stats_nr_tried_attr.attr,
247 &damon_sysfs_stats_sz_tried_attr.attr,
248 &damon_sysfs_stats_nr_applied_attr.attr,
249 &damon_sysfs_stats_sz_applied_attr.attr,
250 &damon_sysfs_stats_qt_exceeds_attr.attr,
253 ATTRIBUTE_GROUPS(damon_sysfs_stats);
255 static struct kobj_type damon_sysfs_stats_ktype = {
256 .release = damon_sysfs_stats_release,
257 .sysfs_ops = &kobj_sysfs_ops,
258 .default_groups = damon_sysfs_stats_groups,
262 * watermarks directory
265 struct damon_sysfs_watermarks {
267 enum damos_wmark_metric metric;
268 unsigned long interval_us;
274 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
275 enum damos_wmark_metric metric, unsigned long interval_us,
276 unsigned long high, unsigned long mid, unsigned long low)
278 struct damon_sysfs_watermarks *watermarks = kmalloc(
279 sizeof(*watermarks), GFP_KERNEL);
283 watermarks->kobj = (struct kobject){};
284 watermarks->metric = metric;
285 watermarks->interval_us = interval_us;
286 watermarks->high = high;
287 watermarks->mid = mid;
288 watermarks->low = low;
292 /* Should match with enum damos_wmark_metric */
293 static const char * const damon_sysfs_wmark_metric_strs[] = {
298 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
301 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
302 struct damon_sysfs_watermarks, kobj);
304 return sysfs_emit(buf, "%s\n",
305 damon_sysfs_wmark_metric_strs[watermarks->metric]);
308 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
309 const char *buf, size_t count)
311 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
312 struct damon_sysfs_watermarks, kobj);
313 enum damos_wmark_metric metric;
315 for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) {
316 if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) {
317 watermarks->metric = metric;
324 static ssize_t interval_us_show(struct kobject *kobj,
325 struct kobj_attribute *attr, char *buf)
327 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
328 struct damon_sysfs_watermarks, kobj);
330 return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
333 static ssize_t interval_us_store(struct kobject *kobj,
334 struct kobj_attribute *attr, const char *buf, size_t count)
336 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
337 struct damon_sysfs_watermarks, kobj);
338 int err = kstrtoul(buf, 0, &watermarks->interval_us);
340 return err ? err : count;
343 static ssize_t high_show(struct kobject *kobj,
344 struct kobj_attribute *attr, char *buf)
346 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
347 struct damon_sysfs_watermarks, kobj);
349 return sysfs_emit(buf, "%lu\n", watermarks->high);
352 static ssize_t high_store(struct kobject *kobj,
353 struct kobj_attribute *attr, const char *buf, size_t count)
355 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
356 struct damon_sysfs_watermarks, kobj);
357 int err = kstrtoul(buf, 0, &watermarks->high);
359 return err ? err : count;
362 static ssize_t mid_show(struct kobject *kobj,
363 struct kobj_attribute *attr, char *buf)
365 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
366 struct damon_sysfs_watermarks, kobj);
368 return sysfs_emit(buf, "%lu\n", watermarks->mid);
371 static ssize_t mid_store(struct kobject *kobj,
372 struct kobj_attribute *attr, const char *buf, size_t count)
374 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
375 struct damon_sysfs_watermarks, kobj);
376 int err = kstrtoul(buf, 0, &watermarks->mid);
378 return err ? err : count;
381 static ssize_t low_show(struct kobject *kobj,
382 struct kobj_attribute *attr, char *buf)
384 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
385 struct damon_sysfs_watermarks, kobj);
387 return sysfs_emit(buf, "%lu\n", watermarks->low);
390 static ssize_t low_store(struct kobject *kobj,
391 struct kobj_attribute *attr, const char *buf, size_t count)
393 struct damon_sysfs_watermarks *watermarks = container_of(kobj,
394 struct damon_sysfs_watermarks, kobj);
395 int err = kstrtoul(buf, 0, &watermarks->low);
397 return err ? err : count;
400 static void damon_sysfs_watermarks_release(struct kobject *kobj)
402 kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
405 static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
406 __ATTR_RW_MODE(metric, 0600);
408 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
409 __ATTR_RW_MODE(interval_us, 0600);
411 static struct kobj_attribute damon_sysfs_watermarks_high_attr =
412 __ATTR_RW_MODE(high, 0600);
414 static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
415 __ATTR_RW_MODE(mid, 0600);
417 static struct kobj_attribute damon_sysfs_watermarks_low_attr =
418 __ATTR_RW_MODE(low, 0600);
420 static struct attribute *damon_sysfs_watermarks_attrs[] = {
421 &damon_sysfs_watermarks_metric_attr.attr,
422 &damon_sysfs_watermarks_interval_us_attr.attr,
423 &damon_sysfs_watermarks_high_attr.attr,
424 &damon_sysfs_watermarks_mid_attr.attr,
425 &damon_sysfs_watermarks_low_attr.attr,
428 ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
430 static struct kobj_type damon_sysfs_watermarks_ktype = {
431 .release = damon_sysfs_watermarks_release,
432 .sysfs_ops = &kobj_sysfs_ops,
433 .default_groups = damon_sysfs_watermarks_groups,
437 * scheme/weights directory
440 struct damon_sysfs_weights {
443 unsigned int nr_accesses;
447 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
448 unsigned int nr_accesses, unsigned int age)
450 struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
455 weights->kobj = (struct kobject){};
457 weights->nr_accesses = nr_accesses;
462 static ssize_t sz_permil_show(struct kobject *kobj,
463 struct kobj_attribute *attr, char *buf)
465 struct damon_sysfs_weights *weights = container_of(kobj,
466 struct damon_sysfs_weights, kobj);
468 return sysfs_emit(buf, "%u\n", weights->sz);
471 static ssize_t sz_permil_store(struct kobject *kobj,
472 struct kobj_attribute *attr, const char *buf, size_t count)
474 struct damon_sysfs_weights *weights = container_of(kobj,
475 struct damon_sysfs_weights, kobj);
476 int err = kstrtouint(buf, 0, &weights->sz);
478 return err ? err : count;
481 static ssize_t nr_accesses_permil_show(struct kobject *kobj,
482 struct kobj_attribute *attr, char *buf)
484 struct damon_sysfs_weights *weights = container_of(kobj,
485 struct damon_sysfs_weights, kobj);
487 return sysfs_emit(buf, "%u\n", weights->nr_accesses);
490 static ssize_t nr_accesses_permil_store(struct kobject *kobj,
491 struct kobj_attribute *attr, const char *buf, size_t count)
493 struct damon_sysfs_weights *weights = container_of(kobj,
494 struct damon_sysfs_weights, kobj);
495 int err = kstrtouint(buf, 0, &weights->nr_accesses);
497 return err ? err : count;
500 static ssize_t age_permil_show(struct kobject *kobj,
501 struct kobj_attribute *attr, char *buf)
503 struct damon_sysfs_weights *weights = container_of(kobj,
504 struct damon_sysfs_weights, kobj);
506 return sysfs_emit(buf, "%u\n", weights->age);
509 static ssize_t age_permil_store(struct kobject *kobj,
510 struct kobj_attribute *attr, const char *buf, size_t count)
512 struct damon_sysfs_weights *weights = container_of(kobj,
513 struct damon_sysfs_weights, kobj);
514 int err = kstrtouint(buf, 0, &weights->age);
516 return err ? err : count;
519 static void damon_sysfs_weights_release(struct kobject *kobj)
521 kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
524 static struct kobj_attribute damon_sysfs_weights_sz_attr =
525 __ATTR_RW_MODE(sz_permil, 0600);
527 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
528 __ATTR_RW_MODE(nr_accesses_permil, 0600);
530 static struct kobj_attribute damon_sysfs_weights_age_attr =
531 __ATTR_RW_MODE(age_permil, 0600);
533 static struct attribute *damon_sysfs_weights_attrs[] = {
534 &damon_sysfs_weights_sz_attr.attr,
535 &damon_sysfs_weights_nr_accesses_attr.attr,
536 &damon_sysfs_weights_age_attr.attr,
539 ATTRIBUTE_GROUPS(damon_sysfs_weights);
541 static struct kobj_type damon_sysfs_weights_ktype = {
542 .release = damon_sysfs_weights_release,
543 .sysfs_ops = &kobj_sysfs_ops,
544 .default_groups = damon_sysfs_weights_groups,
551 struct damon_sysfs_quotas {
553 struct damon_sysfs_weights *weights;
556 unsigned long reset_interval_ms;
559 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
561 return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
564 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
566 struct damon_sysfs_weights *weights;
569 weights = damon_sysfs_weights_alloc(0, 0, 0);
573 err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
574 "as->kobj, "weights");
576 kobject_put(&weights->kobj);
578 quotas->weights = weights;
582 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
584 kobject_put("as->weights->kobj);
587 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
590 struct damon_sysfs_quotas *quotas = container_of(kobj,
591 struct damon_sysfs_quotas, kobj);
593 return sysfs_emit(buf, "%lu\n", quotas->ms);
596 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
597 const char *buf, size_t count)
599 struct damon_sysfs_quotas *quotas = container_of(kobj,
600 struct damon_sysfs_quotas, kobj);
601 int err = kstrtoul(buf, 0, "as->ms);
608 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
611 struct damon_sysfs_quotas *quotas = container_of(kobj,
612 struct damon_sysfs_quotas, kobj);
614 return sysfs_emit(buf, "%lu\n", quotas->sz);
617 static ssize_t bytes_store(struct kobject *kobj,
618 struct kobj_attribute *attr, const char *buf, size_t count)
620 struct damon_sysfs_quotas *quotas = container_of(kobj,
621 struct damon_sysfs_quotas, kobj);
622 int err = kstrtoul(buf, 0, "as->sz);
629 static ssize_t reset_interval_ms_show(struct kobject *kobj,
630 struct kobj_attribute *attr, char *buf)
632 struct damon_sysfs_quotas *quotas = container_of(kobj,
633 struct damon_sysfs_quotas, kobj);
635 return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
638 static ssize_t reset_interval_ms_store(struct kobject *kobj,
639 struct kobj_attribute *attr, const char *buf, size_t count)
641 struct damon_sysfs_quotas *quotas = container_of(kobj,
642 struct damon_sysfs_quotas, kobj);
643 int err = kstrtoul(buf, 0, "as->reset_interval_ms);
650 static void damon_sysfs_quotas_release(struct kobject *kobj)
652 kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
655 static struct kobj_attribute damon_sysfs_quotas_ms_attr =
656 __ATTR_RW_MODE(ms, 0600);
658 static struct kobj_attribute damon_sysfs_quotas_sz_attr =
659 __ATTR_RW_MODE(bytes, 0600);
661 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
662 __ATTR_RW_MODE(reset_interval_ms, 0600);
664 static struct attribute *damon_sysfs_quotas_attrs[] = {
665 &damon_sysfs_quotas_ms_attr.attr,
666 &damon_sysfs_quotas_sz_attr.attr,
667 &damon_sysfs_quotas_reset_interval_ms_attr.attr,
670 ATTRIBUTE_GROUPS(damon_sysfs_quotas);
672 static struct kobj_type damon_sysfs_quotas_ktype = {
673 .release = damon_sysfs_quotas_release,
674 .sysfs_ops = &kobj_sysfs_ops,
675 .default_groups = damon_sysfs_quotas_groups,
679 * access_pattern directory
682 struct damon_sysfs_access_pattern {
684 struct damon_sysfs_ul_range *sz;
685 struct damon_sysfs_ul_range *nr_accesses;
686 struct damon_sysfs_ul_range *age;
690 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void)
692 struct damon_sysfs_access_pattern *access_pattern =
693 kmalloc(sizeof(*access_pattern), GFP_KERNEL);
697 access_pattern->kobj = (struct kobject){};
698 return access_pattern;
701 static int damon_sysfs_access_pattern_add_range_dir(
702 struct damon_sysfs_access_pattern *access_pattern,
703 struct damon_sysfs_ul_range **range_dir_ptr,
706 struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0);
711 err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype,
712 &access_pattern->kobj, name);
714 kobject_put(&range->kobj);
716 *range_dir_ptr = range;
720 static int damon_sysfs_access_pattern_add_dirs(
721 struct damon_sysfs_access_pattern *access_pattern)
725 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
726 &access_pattern->sz, "sz");
730 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
731 &access_pattern->nr_accesses, "nr_accesses");
733 goto put_nr_accesses_sz_out;
735 err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
736 &access_pattern->age, "age");
738 goto put_age_nr_accesses_sz_out;
741 put_age_nr_accesses_sz_out:
742 kobject_put(&access_pattern->age->kobj);
743 access_pattern->age = NULL;
744 put_nr_accesses_sz_out:
745 kobject_put(&access_pattern->nr_accesses->kobj);
746 access_pattern->nr_accesses = NULL;
748 kobject_put(&access_pattern->sz->kobj);
749 access_pattern->sz = NULL;
753 static void damon_sysfs_access_pattern_rm_dirs(
754 struct damon_sysfs_access_pattern *access_pattern)
756 kobject_put(&access_pattern->sz->kobj);
757 kobject_put(&access_pattern->nr_accesses->kobj);
758 kobject_put(&access_pattern->age->kobj);
761 static void damon_sysfs_access_pattern_release(struct kobject *kobj)
763 kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj));
766 static struct attribute *damon_sysfs_access_pattern_attrs[] = {
769 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern);
771 static struct kobj_type damon_sysfs_access_pattern_ktype = {
772 .release = damon_sysfs_access_pattern_release,
773 .sysfs_ops = &kobj_sysfs_ops,
774 .default_groups = damon_sysfs_access_pattern_groups,
781 struct damon_sysfs_scheme {
783 enum damos_action action;
784 struct damon_sysfs_access_pattern *access_pattern;
785 struct damon_sysfs_quotas *quotas;
786 struct damon_sysfs_watermarks *watermarks;
787 struct damon_sysfs_stats *stats;
788 struct damon_sysfs_scheme_regions *tried_regions;
791 /* This should match with enum damos_action */
792 static const char * const damon_sysfs_damos_action_strs[] = {
803 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
804 enum damos_action action)
806 struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme),
811 scheme->kobj = (struct kobject){};
812 scheme->action = action;
816 static int damon_sysfs_scheme_set_access_pattern(
817 struct damon_sysfs_scheme *scheme)
819 struct damon_sysfs_access_pattern *access_pattern;
822 access_pattern = damon_sysfs_access_pattern_alloc();
825 err = kobject_init_and_add(&access_pattern->kobj,
826 &damon_sysfs_access_pattern_ktype, &scheme->kobj,
830 err = damon_sysfs_access_pattern_add_dirs(access_pattern);
833 scheme->access_pattern = access_pattern;
837 kobject_put(&access_pattern->kobj);
841 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
843 struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
848 err = kobject_init_and_add("as->kobj, &damon_sysfs_quotas_ktype,
849 &scheme->kobj, "quotas");
852 err = damon_sysfs_quotas_add_dirs(quotas);
855 scheme->quotas = quotas;
859 kobject_put("as->kobj);
863 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
865 struct damon_sysfs_watermarks *watermarks =
866 damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
871 err = kobject_init_and_add(&watermarks->kobj,
872 &damon_sysfs_watermarks_ktype, &scheme->kobj,
875 kobject_put(&watermarks->kobj);
877 scheme->watermarks = watermarks;
881 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme)
883 struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc();
888 err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype,
889 &scheme->kobj, "stats");
891 kobject_put(&stats->kobj);
893 scheme->stats = stats;
897 static int damon_sysfs_scheme_set_tried_regions(
898 struct damon_sysfs_scheme *scheme)
900 struct damon_sysfs_scheme_regions *tried_regions =
901 damon_sysfs_scheme_regions_alloc();
906 err = kobject_init_and_add(&tried_regions->kobj,
907 &damon_sysfs_scheme_regions_ktype, &scheme->kobj,
910 kobject_put(&tried_regions->kobj);
912 scheme->tried_regions = tried_regions;
916 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
920 err = damon_sysfs_scheme_set_access_pattern(scheme);
923 err = damon_sysfs_scheme_set_quotas(scheme);
925 goto put_access_pattern_out;
926 err = damon_sysfs_scheme_set_watermarks(scheme);
928 goto put_quotas_access_pattern_out;
929 err = damon_sysfs_scheme_set_stats(scheme);
931 goto put_watermarks_quotas_access_pattern_out;
932 err = damon_sysfs_scheme_set_tried_regions(scheme);
934 goto put_tried_regions_out;
937 put_tried_regions_out:
938 kobject_put(&scheme->tried_regions->kobj);
939 scheme->tried_regions = NULL;
940 put_watermarks_quotas_access_pattern_out:
941 kobject_put(&scheme->watermarks->kobj);
942 scheme->watermarks = NULL;
943 put_quotas_access_pattern_out:
944 kobject_put(&scheme->quotas->kobj);
945 scheme->quotas = NULL;
946 put_access_pattern_out:
947 kobject_put(&scheme->access_pattern->kobj);
948 scheme->access_pattern = NULL;
952 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
954 damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
955 kobject_put(&scheme->access_pattern->kobj);
956 damon_sysfs_quotas_rm_dirs(scheme->quotas);
957 kobject_put(&scheme->quotas->kobj);
958 kobject_put(&scheme->watermarks->kobj);
959 kobject_put(&scheme->stats->kobj);
960 damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions);
961 kobject_put(&scheme->tried_regions->kobj);
964 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
967 struct damon_sysfs_scheme *scheme = container_of(kobj,
968 struct damon_sysfs_scheme, kobj);
970 return sysfs_emit(buf, "%s\n",
971 damon_sysfs_damos_action_strs[scheme->action]);
974 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr,
975 const char *buf, size_t count)
977 struct damon_sysfs_scheme *scheme = container_of(kobj,
978 struct damon_sysfs_scheme, kobj);
979 enum damos_action action;
981 for (action = 0; action < NR_DAMOS_ACTIONS; action++) {
982 if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) {
983 scheme->action = action;
990 static void damon_sysfs_scheme_release(struct kobject *kobj)
992 kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
995 static struct kobj_attribute damon_sysfs_scheme_action_attr =
996 __ATTR_RW_MODE(action, 0600);
998 static struct attribute *damon_sysfs_scheme_attrs[] = {
999 &damon_sysfs_scheme_action_attr.attr,
1002 ATTRIBUTE_GROUPS(damon_sysfs_scheme);
1004 static struct kobj_type damon_sysfs_scheme_ktype = {
1005 .release = damon_sysfs_scheme_release,
1006 .sysfs_ops = &kobj_sysfs_ops,
1007 .default_groups = damon_sysfs_scheme_groups,
1014 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void)
1016 return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL);
1019 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes)
1021 struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr;
1024 for (i = 0; i < schemes->nr; i++) {
1025 damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
1026 kobject_put(&schemes_arr[i]->kobj);
1030 schemes->schemes_arr = NULL;
1033 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes,
1036 struct damon_sysfs_scheme **schemes_arr, *scheme;
1039 damon_sysfs_schemes_rm_dirs(schemes);
1043 schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr),
1044 GFP_KERNEL | __GFP_NOWARN);
1047 schemes->schemes_arr = schemes_arr;
1049 for (i = 0; i < nr_schemes; i++) {
1050 scheme = damon_sysfs_scheme_alloc(DAMOS_STAT);
1052 damon_sysfs_schemes_rm_dirs(schemes);
1056 err = kobject_init_and_add(&scheme->kobj,
1057 &damon_sysfs_scheme_ktype, &schemes->kobj,
1061 err = damon_sysfs_scheme_add_dirs(scheme);
1065 schemes_arr[i] = scheme;
1071 damon_sysfs_schemes_rm_dirs(schemes);
1072 kobject_put(&scheme->kobj);
1076 static ssize_t nr_schemes_show(struct kobject *kobj,
1077 struct kobj_attribute *attr, char *buf)
1079 struct damon_sysfs_schemes *schemes = container_of(kobj,
1080 struct damon_sysfs_schemes, kobj);
1082 return sysfs_emit(buf, "%d\n", schemes->nr);
1085 static ssize_t nr_schemes_store(struct kobject *kobj,
1086 struct kobj_attribute *attr, const char *buf, size_t count)
1088 struct damon_sysfs_schemes *schemes;
1089 int nr, err = kstrtoint(buf, 0, &nr);
1096 schemes = container_of(kobj, struct damon_sysfs_schemes, kobj);
1098 if (!mutex_trylock(&damon_sysfs_lock))
1100 err = damon_sysfs_schemes_add_dirs(schemes, nr);
1101 mutex_unlock(&damon_sysfs_lock);
1107 static void damon_sysfs_schemes_release(struct kobject *kobj)
1109 kfree(container_of(kobj, struct damon_sysfs_schemes, kobj));
1112 static struct kobj_attribute damon_sysfs_schemes_nr_attr =
1113 __ATTR_RW_MODE(nr_schemes, 0600);
1115 static struct attribute *damon_sysfs_schemes_attrs[] = {
1116 &damon_sysfs_schemes_nr_attr.attr,
1119 ATTRIBUTE_GROUPS(damon_sysfs_schemes);
1121 struct kobj_type damon_sysfs_schemes_ktype = {
1122 .release = damon_sysfs_schemes_release,
1123 .sysfs_ops = &kobj_sysfs_ops,
1124 .default_groups = damon_sysfs_schemes_groups,
1127 static struct damos *damon_sysfs_mk_scheme(
1128 struct damon_sysfs_scheme *sysfs_scheme)
1130 struct damon_sysfs_access_pattern *access_pattern =
1131 sysfs_scheme->access_pattern;
1132 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1133 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1134 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1136 struct damos_access_pattern pattern = {
1137 .min_sz_region = access_pattern->sz->min,
1138 .max_sz_region = access_pattern->sz->max,
1139 .min_nr_accesses = access_pattern->nr_accesses->min,
1140 .max_nr_accesses = access_pattern->nr_accesses->max,
1141 .min_age_region = access_pattern->age->min,
1142 .max_age_region = access_pattern->age->max,
1144 struct damos_quota quota = {
1145 .ms = sysfs_quotas->ms,
1146 .sz = sysfs_quotas->sz,
1147 .reset_interval = sysfs_quotas->reset_interval_ms,
1148 .weight_sz = sysfs_weights->sz,
1149 .weight_nr_accesses = sysfs_weights->nr_accesses,
1150 .weight_age = sysfs_weights->age,
1152 struct damos_watermarks wmarks = {
1153 .metric = sysfs_wmarks->metric,
1154 .interval = sysfs_wmarks->interval_us,
1155 .high = sysfs_wmarks->high,
1156 .mid = sysfs_wmarks->mid,
1157 .low = sysfs_wmarks->low,
1160 return damon_new_scheme(&pattern, sysfs_scheme->action, "a,
1164 static void damon_sysfs_update_scheme(struct damos *scheme,
1165 struct damon_sysfs_scheme *sysfs_scheme)
1167 struct damon_sysfs_access_pattern *access_pattern =
1168 sysfs_scheme->access_pattern;
1169 struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1170 struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1171 struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1173 scheme->pattern.min_sz_region = access_pattern->sz->min;
1174 scheme->pattern.max_sz_region = access_pattern->sz->max;
1175 scheme->pattern.min_nr_accesses = access_pattern->nr_accesses->min;
1176 scheme->pattern.max_nr_accesses = access_pattern->nr_accesses->max;
1177 scheme->pattern.min_age_region = access_pattern->age->min;
1178 scheme->pattern.max_age_region = access_pattern->age->max;
1180 scheme->action = sysfs_scheme->action;
1182 scheme->quota.ms = sysfs_quotas->ms;
1183 scheme->quota.sz = sysfs_quotas->sz;
1184 scheme->quota.reset_interval = sysfs_quotas->reset_interval_ms;
1185 scheme->quota.weight_sz = sysfs_weights->sz;
1186 scheme->quota.weight_nr_accesses = sysfs_weights->nr_accesses;
1187 scheme->quota.weight_age = sysfs_weights->age;
1189 scheme->wmarks.metric = sysfs_wmarks->metric;
1190 scheme->wmarks.interval = sysfs_wmarks->interval_us;
1191 scheme->wmarks.high = sysfs_wmarks->high;
1192 scheme->wmarks.mid = sysfs_wmarks->mid;
1193 scheme->wmarks.low = sysfs_wmarks->low;
1196 int damon_sysfs_set_schemes(struct damon_ctx *ctx,
1197 struct damon_sysfs_schemes *sysfs_schemes)
1199 struct damos *scheme, *next;
1202 damon_for_each_scheme_safe(scheme, next, ctx) {
1203 if (i < sysfs_schemes->nr)
1204 damon_sysfs_update_scheme(scheme,
1205 sysfs_schemes->schemes_arr[i]);
1207 damon_destroy_scheme(scheme);
1211 for (; i < sysfs_schemes->nr; i++) {
1212 struct damos *scheme, *next;
1214 scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]);
1216 damon_for_each_scheme_safe(scheme, next, ctx)
1217 damon_destroy_scheme(scheme);
1220 damon_add_scheme(ctx, scheme);
1225 void damon_sysfs_schemes_update_stats(
1226 struct damon_sysfs_schemes *sysfs_schemes,
1227 struct damon_ctx *ctx)
1229 struct damos *scheme;
1230 int schemes_idx = 0;
1232 damon_for_each_scheme(scheme, ctx) {
1233 struct damon_sysfs_stats *sysfs_stats;
1235 /* user could have removed the scheme sysfs dir */
1236 if (schemes_idx >= sysfs_schemes->nr)
1239 sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats;
1240 sysfs_stats->nr_tried = scheme->stat.nr_tried;
1241 sysfs_stats->sz_tried = scheme->stat.sz_tried;
1242 sysfs_stats->nr_applied = scheme->stat.nr_applied;
1243 sysfs_stats->sz_applied = scheme->stat.sz_applied;
1244 sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds;
1249 * damon_sysfs_schemes that need to update its schemes regions dir. Protected
1250 * by damon_sysfs_lock
1252 static struct damon_sysfs_schemes *damon_sysfs_schemes_for_damos_callback;
1253 static int damon_sysfs_schemes_region_idx;
1256 * DAMON callback that called before damos apply. While this callback is
1257 * registered, damon_sysfs_lock should be held to ensure the regions
1258 * directories exist.
1260 static int damon_sysfs_before_damos_apply(struct damon_ctx *ctx,
1261 struct damon_target *t, struct damon_region *r,
1264 struct damos *scheme;
1265 struct damon_sysfs_scheme_regions *sysfs_regions;
1266 struct damon_sysfs_scheme_region *region;
1267 struct damon_sysfs_schemes *sysfs_schemes =
1268 damon_sysfs_schemes_for_damos_callback;
1269 int schemes_idx = 0;
1271 damon_for_each_scheme(scheme, ctx) {
1277 /* user could have removed the scheme sysfs dir */
1278 if (schemes_idx >= sysfs_schemes->nr)
1281 sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions;
1282 region = damon_sysfs_scheme_region_alloc(r);
1283 list_add_tail(®ion->list, &sysfs_regions->regions_list);
1284 sysfs_regions->nr_regions++;
1285 if (kobject_init_and_add(®ion->kobj,
1286 &damon_sysfs_scheme_region_ktype,
1287 &sysfs_regions->kobj, "%d",
1288 damon_sysfs_schemes_region_idx++)) {
1289 kobject_put(®ion->kobj);
1294 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1295 int damon_sysfs_schemes_clear_regions(
1296 struct damon_sysfs_schemes *sysfs_schemes,
1297 struct damon_ctx *ctx)
1299 struct damos *scheme;
1300 int schemes_idx = 0;
1302 damon_for_each_scheme(scheme, ctx) {
1303 struct damon_sysfs_scheme *sysfs_scheme;
1305 /* user could have removed the scheme sysfs dir */
1306 if (schemes_idx >= sysfs_schemes->nr)
1309 sysfs_scheme = sysfs_schemes->schemes_arr[schemes_idx++];
1310 damon_sysfs_scheme_regions_rm_dirs(
1311 sysfs_scheme->tried_regions);
1316 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1317 int damon_sysfs_schemes_update_regions_start(
1318 struct damon_sysfs_schemes *sysfs_schemes,
1319 struct damon_ctx *ctx)
1321 damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx);
1322 damon_sysfs_schemes_for_damos_callback = sysfs_schemes;
1323 ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply;
1328 * Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock. Caller
1329 * should unlock damon_sysfs_lock which held before
1330 * damon_sysfs_schemes_update_regions_start()
1332 int damon_sysfs_schemes_update_regions_stop(struct damon_ctx *ctx)
1334 damon_sysfs_schemes_for_damos_callback = NULL;
1335 ctx->callback.before_damos_apply = NULL;
1336 damon_sysfs_schemes_region_idx = 0;