xref: /openbmc/linux/mm/damon/sysfs-schemes.c (revision ea7f03a4)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * DAMON sysfs Interface
4  *
5  * Copyright (c) 2022 SeongJae Park <sj@kernel.org>
6  */
7 
8 #include <linux/slab.h>
9 
10 #include "sysfs-common.h"
11 
12 /*
13  * scheme region directory
14  */
15 
16 struct damon_sysfs_scheme_region {
17 	struct kobject kobj;
18 	struct damon_addr_range ar;
19 	unsigned int nr_accesses;
20 	unsigned int age;
21 	struct list_head list;
22 };
23 
24 static struct damon_sysfs_scheme_region *damon_sysfs_scheme_region_alloc(
25 		struct damon_region *region)
26 {
27 	struct damon_sysfs_scheme_region *sysfs_region = kmalloc(
28 			sizeof(*sysfs_region), GFP_KERNEL);
29 
30 	if (!sysfs_region)
31 		return NULL;
32 	sysfs_region->kobj = (struct kobject){};
33 	sysfs_region->ar = region->ar;
34 	sysfs_region->nr_accesses = region->nr_accesses;
35 	sysfs_region->age = region->age;
36 	INIT_LIST_HEAD(&sysfs_region->list);
37 	return sysfs_region;
38 }
39 
40 static ssize_t start_show(struct kobject *kobj, struct kobj_attribute *attr,
41 		char *buf)
42 {
43 	struct damon_sysfs_scheme_region *region = container_of(kobj,
44 			struct damon_sysfs_scheme_region, kobj);
45 
46 	return sysfs_emit(buf, "%lu\n", region->ar.start);
47 }
48 
49 static ssize_t end_show(struct kobject *kobj, struct kobj_attribute *attr,
50 		char *buf)
51 {
52 	struct damon_sysfs_scheme_region *region = container_of(kobj,
53 			struct damon_sysfs_scheme_region, kobj);
54 
55 	return sysfs_emit(buf, "%lu\n", region->ar.end);
56 }
57 
58 static ssize_t nr_accesses_show(struct kobject *kobj,
59 		struct kobj_attribute *attr, char *buf)
60 {
61 	struct damon_sysfs_scheme_region *region = container_of(kobj,
62 			struct damon_sysfs_scheme_region, kobj);
63 
64 	return sysfs_emit(buf, "%u\n", region->nr_accesses);
65 }
66 
67 static ssize_t age_show(struct kobject *kobj, struct kobj_attribute *attr,
68 		char *buf)
69 {
70 	struct damon_sysfs_scheme_region *region = container_of(kobj,
71 			struct damon_sysfs_scheme_region, kobj);
72 
73 	return sysfs_emit(buf, "%u\n", region->age);
74 }
75 
76 static void damon_sysfs_scheme_region_release(struct kobject *kobj)
77 {
78 	struct damon_sysfs_scheme_region *region = container_of(kobj,
79 			struct damon_sysfs_scheme_region, kobj);
80 
81 	list_del(&region->list);
82 	kfree(region);
83 }
84 
85 static struct kobj_attribute damon_sysfs_scheme_region_start_attr =
86 		__ATTR_RO_MODE(start, 0400);
87 
88 static struct kobj_attribute damon_sysfs_scheme_region_end_attr =
89 		__ATTR_RO_MODE(end, 0400);
90 
91 static struct kobj_attribute damon_sysfs_scheme_region_nr_accesses_attr =
92 		__ATTR_RO_MODE(nr_accesses, 0400);
93 
94 static struct kobj_attribute damon_sysfs_scheme_region_age_attr =
95 		__ATTR_RO_MODE(age, 0400);
96 
97 static struct attribute *damon_sysfs_scheme_region_attrs[] = {
98 	&damon_sysfs_scheme_region_start_attr.attr,
99 	&damon_sysfs_scheme_region_end_attr.attr,
100 	&damon_sysfs_scheme_region_nr_accesses_attr.attr,
101 	&damon_sysfs_scheme_region_age_attr.attr,
102 	NULL,
103 };
104 ATTRIBUTE_GROUPS(damon_sysfs_scheme_region);
105 
106 static 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,
110 };
111 
112 /*
113  * scheme regions directory
114  */
115 
116 struct damon_sysfs_scheme_regions {
117 	struct kobject kobj;
118 	struct list_head regions_list;
119 	int nr_regions;
120 	unsigned long total_bytes;
121 };
122 
123 static struct damon_sysfs_scheme_regions *
124 damon_sysfs_scheme_regions_alloc(void)
125 {
126 	struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions),
127 			GFP_KERNEL);
128 
129 	regions->kobj = (struct kobject){};
130 	INIT_LIST_HEAD(&regions->regions_list);
131 	regions->nr_regions = 0;
132 	regions->total_bytes = 0;
133 	return regions;
134 }
135 
136 static ssize_t total_bytes_show(struct kobject *kobj,
137 		struct kobj_attribute *attr, char *buf)
138 {
139 	struct damon_sysfs_scheme_regions *regions = container_of(kobj,
140 			struct damon_sysfs_scheme_regions, kobj);
141 
142 	return sysfs_emit(buf, "%lu\n", regions->total_bytes);
143 }
144 
145 static void damon_sysfs_scheme_regions_rm_dirs(
146 		struct damon_sysfs_scheme_regions *regions)
147 {
148 	struct damon_sysfs_scheme_region *r, *next;
149 
150 	list_for_each_entry_safe(r, next, &regions->regions_list, list) {
151 		/* release function deletes it from the list */
152 		kobject_put(&r->kobj);
153 		regions->nr_regions--;
154 	}
155 }
156 
157 static void damon_sysfs_scheme_regions_release(struct kobject *kobj)
158 {
159 	kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj));
160 }
161 
162 static struct kobj_attribute damon_sysfs_scheme_regions_total_bytes_attr =
163 		__ATTR_RO_MODE(total_bytes, 0400);
164 
165 static struct attribute *damon_sysfs_scheme_regions_attrs[] = {
166 	&damon_sysfs_scheme_regions_total_bytes_attr.attr,
167 	NULL,
168 };
169 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions);
170 
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,
175 };
176 
177 /*
178  * schemes/stats directory
179  */
180 
181 struct damon_sysfs_stats {
182 	struct kobject kobj;
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;
188 };
189 
190 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void)
191 {
192 	return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL);
193 }
194 
195 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
196 		char *buf)
197 {
198 	struct damon_sysfs_stats *stats = container_of(kobj,
199 			struct damon_sysfs_stats, kobj);
200 
201 	return sysfs_emit(buf, "%lu\n", stats->nr_tried);
202 }
203 
204 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
205 		char *buf)
206 {
207 	struct damon_sysfs_stats *stats = container_of(kobj,
208 			struct damon_sysfs_stats, kobj);
209 
210 	return sysfs_emit(buf, "%lu\n", stats->sz_tried);
211 }
212 
213 static ssize_t nr_applied_show(struct kobject *kobj,
214 		struct kobj_attribute *attr, char *buf)
215 {
216 	struct damon_sysfs_stats *stats = container_of(kobj,
217 			struct damon_sysfs_stats, kobj);
218 
219 	return sysfs_emit(buf, "%lu\n", stats->nr_applied);
220 }
221 
222 static ssize_t sz_applied_show(struct kobject *kobj,
223 		struct kobj_attribute *attr, char *buf)
224 {
225 	struct damon_sysfs_stats *stats = container_of(kobj,
226 			struct damon_sysfs_stats, kobj);
227 
228 	return sysfs_emit(buf, "%lu\n", stats->sz_applied);
229 }
230 
231 static ssize_t qt_exceeds_show(struct kobject *kobj,
232 		struct kobj_attribute *attr, char *buf)
233 {
234 	struct damon_sysfs_stats *stats = container_of(kobj,
235 			struct damon_sysfs_stats, kobj);
236 
237 	return sysfs_emit(buf, "%lu\n", stats->qt_exceeds);
238 }
239 
240 static void damon_sysfs_stats_release(struct kobject *kobj)
241 {
242 	kfree(container_of(kobj, struct damon_sysfs_stats, kobj));
243 }
244 
245 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr =
246 		__ATTR_RO_MODE(nr_tried, 0400);
247 
248 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr =
249 		__ATTR_RO_MODE(sz_tried, 0400);
250 
251 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr =
252 		__ATTR_RO_MODE(nr_applied, 0400);
253 
254 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr =
255 		__ATTR_RO_MODE(sz_applied, 0400);
256 
257 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr =
258 		__ATTR_RO_MODE(qt_exceeds, 0400);
259 
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,
266 	NULL,
267 };
268 ATTRIBUTE_GROUPS(damon_sysfs_stats);
269 
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,
274 };
275 
276 /*
277  * filter directory
278  */
279 
280 struct damon_sysfs_scheme_filter {
281 	struct kobject kobj;
282 	enum damos_filter_type type;
283 	bool matching;
284 	char *memcg_path;
285 };
286 
287 static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc(void)
288 {
289 	return kzalloc(sizeof(struct damon_sysfs_scheme_filter), GFP_KERNEL);
290 }
291 
292 /* Should match with enum damos_filter_type */
293 static const char * const damon_sysfs_scheme_filter_type_strs[] = {
294 	"anon",
295 	"memcg",
296 };
297 
298 static ssize_t type_show(struct kobject *kobj,
299 		struct kobj_attribute *attr, char *buf)
300 {
301 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
302 			struct damon_sysfs_scheme_filter, kobj);
303 
304 	return sysfs_emit(buf, "%s\n",
305 			damon_sysfs_scheme_filter_type_strs[filter->type]);
306 }
307 
308 static ssize_t type_store(struct kobject *kobj,
309 		struct kobj_attribute *attr, const char *buf, size_t count)
310 {
311 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
312 			struct damon_sysfs_scheme_filter, kobj);
313 	enum damos_filter_type type;
314 	ssize_t ret = -EINVAL;
315 
316 	for (type = 0; type < NR_DAMOS_FILTER_TYPES; type++) {
317 		if (sysfs_streq(buf, damon_sysfs_scheme_filter_type_strs[
318 					type])) {
319 			filter->type = type;
320 			ret = count;
321 			break;
322 		}
323 	}
324 	return ret;
325 }
326 
327 static ssize_t matching_show(struct kobject *kobj,
328 		struct kobj_attribute *attr, char *buf)
329 {
330 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
331 			struct damon_sysfs_scheme_filter, kobj);
332 
333 	return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N');
334 }
335 
336 static ssize_t matching_store(struct kobject *kobj,
337 		struct kobj_attribute *attr, const char *buf, size_t count)
338 {
339 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
340 			struct damon_sysfs_scheme_filter, kobj);
341 	bool matching;
342 	int err = kstrtobool(buf, &matching);
343 
344 	if (err)
345 		return err;
346 
347 	filter->matching = matching;
348 	return count;
349 }
350 
351 static ssize_t memcg_path_show(struct kobject *kobj,
352 		struct kobj_attribute *attr, char *buf)
353 {
354 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
355 			struct damon_sysfs_scheme_filter, kobj);
356 
357 	return sysfs_emit(buf, "%s\n",
358 			filter->memcg_path ? filter->memcg_path : "");
359 }
360 
361 static ssize_t memcg_path_store(struct kobject *kobj,
362 		struct kobj_attribute *attr, const char *buf, size_t count)
363 {
364 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
365 			struct damon_sysfs_scheme_filter, kobj);
366 	char *path = kmalloc(sizeof(*path) * (count + 1), GFP_KERNEL);
367 
368 	if (!path)
369 		return -ENOMEM;
370 
371 	strscpy(path, buf, count + 1);
372 	filter->memcg_path = path;
373 	return count;
374 }
375 
376 static void damon_sysfs_scheme_filter_release(struct kobject *kobj)
377 {
378 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
379 			struct damon_sysfs_scheme_filter, kobj);
380 
381 	kfree(filter->memcg_path);
382 	kfree(filter);
383 }
384 
385 static struct kobj_attribute damon_sysfs_scheme_filter_type_attr =
386 		__ATTR_RW_MODE(type, 0600);
387 
388 static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr =
389 		__ATTR_RW_MODE(matching, 0600);
390 
391 static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr =
392 		__ATTR_RW_MODE(memcg_path, 0600);
393 
394 static struct attribute *damon_sysfs_scheme_filter_attrs[] = {
395 	&damon_sysfs_scheme_filter_type_attr.attr,
396 	&damon_sysfs_scheme_filter_matching_attr.attr,
397 	&damon_sysfs_scheme_filter_memcg_path_attr.attr,
398 	NULL,
399 };
400 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter);
401 
402 static const struct kobj_type damon_sysfs_scheme_filter_ktype = {
403 	.release = damon_sysfs_scheme_filter_release,
404 	.sysfs_ops = &kobj_sysfs_ops,
405 	.default_groups = damon_sysfs_scheme_filter_groups,
406 };
407 
408 /*
409  * filters directory
410  */
411 
412 struct damon_sysfs_scheme_filters {
413 	struct kobject kobj;
414 	struct damon_sysfs_scheme_filter **filters_arr;
415 	int nr;
416 };
417 
418 static struct damon_sysfs_scheme_filters *
419 damon_sysfs_scheme_filters_alloc(void)
420 {
421 	return kzalloc(sizeof(struct damon_sysfs_scheme_filters), GFP_KERNEL);
422 }
423 
424 static void damon_sysfs_scheme_filters_rm_dirs(
425 		struct damon_sysfs_scheme_filters *filters)
426 {
427 	struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr;
428 	int i;
429 
430 	for (i = 0; i < filters->nr; i++)
431 		kobject_put(&filters_arr[i]->kobj);
432 	filters->nr = 0;
433 	kfree(filters_arr);
434 	filters->filters_arr = NULL;
435 }
436 
437 static int damon_sysfs_scheme_filters_add_dirs(
438 		struct damon_sysfs_scheme_filters *filters, int nr_filters)
439 {
440 	struct damon_sysfs_scheme_filter **filters_arr, *filter;
441 	int err, i;
442 
443 	damon_sysfs_scheme_filters_rm_dirs(filters);
444 	if (!nr_filters)
445 		return 0;
446 
447 	filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr),
448 			GFP_KERNEL | __GFP_NOWARN);
449 	if (!filters_arr)
450 		return -ENOMEM;
451 	filters->filters_arr = filters_arr;
452 
453 	for (i = 0; i < nr_filters; i++) {
454 		filter = damon_sysfs_scheme_filter_alloc();
455 		if (!filter) {
456 			damon_sysfs_scheme_filters_rm_dirs(filters);
457 			return -ENOMEM;
458 		}
459 
460 		err = kobject_init_and_add(&filter->kobj,
461 				&damon_sysfs_scheme_filter_ktype,
462 				&filters->kobj, "%d", i);
463 		if (err) {
464 			kobject_put(&filter->kobj);
465 			damon_sysfs_scheme_filters_rm_dirs(filters);
466 			return err;
467 		}
468 
469 		filters_arr[i] = filter;
470 		filters->nr++;
471 	}
472 	return 0;
473 }
474 
475 static ssize_t nr_filters_show(struct kobject *kobj,
476 		struct kobj_attribute *attr, char *buf)
477 {
478 	struct damon_sysfs_scheme_filters *filters = container_of(kobj,
479 			struct damon_sysfs_scheme_filters, kobj);
480 
481 	return sysfs_emit(buf, "%d\n", filters->nr);
482 }
483 
484 static ssize_t nr_filters_store(struct kobject *kobj,
485 		struct kobj_attribute *attr, const char *buf, size_t count)
486 {
487 	struct damon_sysfs_scheme_filters *filters;
488 	int nr, err = kstrtoint(buf, 0, &nr);
489 
490 	if (err)
491 		return err;
492 	if (nr < 0)
493 		return -EINVAL;
494 
495 	filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj);
496 
497 	if (!mutex_trylock(&damon_sysfs_lock))
498 		return -EBUSY;
499 	err = damon_sysfs_scheme_filters_add_dirs(filters, nr);
500 	mutex_unlock(&damon_sysfs_lock);
501 	if (err)
502 		return err;
503 
504 	return count;
505 }
506 
507 static void damon_sysfs_scheme_filters_release(struct kobject *kobj)
508 {
509 	kfree(container_of(kobj, struct damon_sysfs_scheme_filters, kobj));
510 }
511 
512 static struct kobj_attribute damon_sysfs_scheme_filters_nr_attr =
513 		__ATTR_RW_MODE(nr_filters, 0600);
514 
515 static struct attribute *damon_sysfs_scheme_filters_attrs[] = {
516 	&damon_sysfs_scheme_filters_nr_attr.attr,
517 	NULL,
518 };
519 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filters);
520 
521 static const struct kobj_type damon_sysfs_scheme_filters_ktype = {
522 	.release = damon_sysfs_scheme_filters_release,
523 	.sysfs_ops = &kobj_sysfs_ops,
524 	.default_groups = damon_sysfs_scheme_filters_groups,
525 };
526 
527 /*
528  * watermarks directory
529  */
530 
531 struct damon_sysfs_watermarks {
532 	struct kobject kobj;
533 	enum damos_wmark_metric metric;
534 	unsigned long interval_us;
535 	unsigned long high;
536 	unsigned long mid;
537 	unsigned long low;
538 };
539 
540 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
541 		enum damos_wmark_metric metric, unsigned long interval_us,
542 		unsigned long high, unsigned long mid, unsigned long low)
543 {
544 	struct damon_sysfs_watermarks *watermarks = kmalloc(
545 			sizeof(*watermarks), GFP_KERNEL);
546 
547 	if (!watermarks)
548 		return NULL;
549 	watermarks->kobj = (struct kobject){};
550 	watermarks->metric = metric;
551 	watermarks->interval_us = interval_us;
552 	watermarks->high = high;
553 	watermarks->mid = mid;
554 	watermarks->low = low;
555 	return watermarks;
556 }
557 
558 /* Should match with enum damos_wmark_metric */
559 static const char * const damon_sysfs_wmark_metric_strs[] = {
560 	"none",
561 	"free_mem_rate",
562 };
563 
564 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
565 		char *buf)
566 {
567 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
568 			struct damon_sysfs_watermarks, kobj);
569 
570 	return sysfs_emit(buf, "%s\n",
571 			damon_sysfs_wmark_metric_strs[watermarks->metric]);
572 }
573 
574 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
575 		const char *buf, size_t count)
576 {
577 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
578 			struct damon_sysfs_watermarks, kobj);
579 	enum damos_wmark_metric metric;
580 
581 	for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) {
582 		if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) {
583 			watermarks->metric = metric;
584 			return count;
585 		}
586 	}
587 	return -EINVAL;
588 }
589 
590 static ssize_t interval_us_show(struct kobject *kobj,
591 		struct kobj_attribute *attr, char *buf)
592 {
593 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
594 			struct damon_sysfs_watermarks, kobj);
595 
596 	return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
597 }
598 
599 static ssize_t interval_us_store(struct kobject *kobj,
600 		struct kobj_attribute *attr, const char *buf, size_t count)
601 {
602 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
603 			struct damon_sysfs_watermarks, kobj);
604 	int err = kstrtoul(buf, 0, &watermarks->interval_us);
605 
606 	return err ? err : count;
607 }
608 
609 static ssize_t high_show(struct kobject *kobj,
610 		struct kobj_attribute *attr, char *buf)
611 {
612 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
613 			struct damon_sysfs_watermarks, kobj);
614 
615 	return sysfs_emit(buf, "%lu\n", watermarks->high);
616 }
617 
618 static ssize_t high_store(struct kobject *kobj,
619 		struct kobj_attribute *attr, const char *buf, size_t count)
620 {
621 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
622 			struct damon_sysfs_watermarks, kobj);
623 	int err = kstrtoul(buf, 0, &watermarks->high);
624 
625 	return err ? err : count;
626 }
627 
628 static ssize_t mid_show(struct kobject *kobj,
629 		struct kobj_attribute *attr, char *buf)
630 {
631 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
632 			struct damon_sysfs_watermarks, kobj);
633 
634 	return sysfs_emit(buf, "%lu\n", watermarks->mid);
635 }
636 
637 static ssize_t mid_store(struct kobject *kobj,
638 		struct kobj_attribute *attr, const char *buf, size_t count)
639 {
640 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
641 			struct damon_sysfs_watermarks, kobj);
642 	int err = kstrtoul(buf, 0, &watermarks->mid);
643 
644 	return err ? err : count;
645 }
646 
647 static ssize_t low_show(struct kobject *kobj,
648 		struct kobj_attribute *attr, char *buf)
649 {
650 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
651 			struct damon_sysfs_watermarks, kobj);
652 
653 	return sysfs_emit(buf, "%lu\n", watermarks->low);
654 }
655 
656 static ssize_t low_store(struct kobject *kobj,
657 		struct kobj_attribute *attr, const char *buf, size_t count)
658 {
659 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
660 			struct damon_sysfs_watermarks, kobj);
661 	int err = kstrtoul(buf, 0, &watermarks->low);
662 
663 	return err ? err : count;
664 }
665 
666 static void damon_sysfs_watermarks_release(struct kobject *kobj)
667 {
668 	kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
669 }
670 
671 static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
672 		__ATTR_RW_MODE(metric, 0600);
673 
674 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
675 		__ATTR_RW_MODE(interval_us, 0600);
676 
677 static struct kobj_attribute damon_sysfs_watermarks_high_attr =
678 		__ATTR_RW_MODE(high, 0600);
679 
680 static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
681 		__ATTR_RW_MODE(mid, 0600);
682 
683 static struct kobj_attribute damon_sysfs_watermarks_low_attr =
684 		__ATTR_RW_MODE(low, 0600);
685 
686 static struct attribute *damon_sysfs_watermarks_attrs[] = {
687 	&damon_sysfs_watermarks_metric_attr.attr,
688 	&damon_sysfs_watermarks_interval_us_attr.attr,
689 	&damon_sysfs_watermarks_high_attr.attr,
690 	&damon_sysfs_watermarks_mid_attr.attr,
691 	&damon_sysfs_watermarks_low_attr.attr,
692 	NULL,
693 };
694 ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
695 
696 static const struct kobj_type damon_sysfs_watermarks_ktype = {
697 	.release = damon_sysfs_watermarks_release,
698 	.sysfs_ops = &kobj_sysfs_ops,
699 	.default_groups = damon_sysfs_watermarks_groups,
700 };
701 
702 /*
703  * scheme/weights directory
704  */
705 
706 struct damon_sysfs_weights {
707 	struct kobject kobj;
708 	unsigned int sz;
709 	unsigned int nr_accesses;
710 	unsigned int age;
711 };
712 
713 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
714 		unsigned int nr_accesses, unsigned int age)
715 {
716 	struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
717 			GFP_KERNEL);
718 
719 	if (!weights)
720 		return NULL;
721 	weights->kobj = (struct kobject){};
722 	weights->sz = sz;
723 	weights->nr_accesses = nr_accesses;
724 	weights->age = age;
725 	return weights;
726 }
727 
728 static ssize_t sz_permil_show(struct kobject *kobj,
729 		struct kobj_attribute *attr, char *buf)
730 {
731 	struct damon_sysfs_weights *weights = container_of(kobj,
732 			struct damon_sysfs_weights, kobj);
733 
734 	return sysfs_emit(buf, "%u\n", weights->sz);
735 }
736 
737 static ssize_t sz_permil_store(struct kobject *kobj,
738 		struct kobj_attribute *attr, const char *buf, size_t count)
739 {
740 	struct damon_sysfs_weights *weights = container_of(kobj,
741 			struct damon_sysfs_weights, kobj);
742 	int err = kstrtouint(buf, 0, &weights->sz);
743 
744 	return err ? err : count;
745 }
746 
747 static ssize_t nr_accesses_permil_show(struct kobject *kobj,
748 		struct kobj_attribute *attr, char *buf)
749 {
750 	struct damon_sysfs_weights *weights = container_of(kobj,
751 			struct damon_sysfs_weights, kobj);
752 
753 	return sysfs_emit(buf, "%u\n", weights->nr_accesses);
754 }
755 
756 static ssize_t nr_accesses_permil_store(struct kobject *kobj,
757 		struct kobj_attribute *attr, const char *buf, size_t count)
758 {
759 	struct damon_sysfs_weights *weights = container_of(kobj,
760 			struct damon_sysfs_weights, kobj);
761 	int err = kstrtouint(buf, 0, &weights->nr_accesses);
762 
763 	return err ? err : count;
764 }
765 
766 static ssize_t age_permil_show(struct kobject *kobj,
767 		struct kobj_attribute *attr, char *buf)
768 {
769 	struct damon_sysfs_weights *weights = container_of(kobj,
770 			struct damon_sysfs_weights, kobj);
771 
772 	return sysfs_emit(buf, "%u\n", weights->age);
773 }
774 
775 static ssize_t age_permil_store(struct kobject *kobj,
776 		struct kobj_attribute *attr, const char *buf, size_t count)
777 {
778 	struct damon_sysfs_weights *weights = container_of(kobj,
779 			struct damon_sysfs_weights, kobj);
780 	int err = kstrtouint(buf, 0, &weights->age);
781 
782 	return err ? err : count;
783 }
784 
785 static void damon_sysfs_weights_release(struct kobject *kobj)
786 {
787 	kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
788 }
789 
790 static struct kobj_attribute damon_sysfs_weights_sz_attr =
791 		__ATTR_RW_MODE(sz_permil, 0600);
792 
793 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
794 		__ATTR_RW_MODE(nr_accesses_permil, 0600);
795 
796 static struct kobj_attribute damon_sysfs_weights_age_attr =
797 		__ATTR_RW_MODE(age_permil, 0600);
798 
799 static struct attribute *damon_sysfs_weights_attrs[] = {
800 	&damon_sysfs_weights_sz_attr.attr,
801 	&damon_sysfs_weights_nr_accesses_attr.attr,
802 	&damon_sysfs_weights_age_attr.attr,
803 	NULL,
804 };
805 ATTRIBUTE_GROUPS(damon_sysfs_weights);
806 
807 static const struct kobj_type damon_sysfs_weights_ktype = {
808 	.release = damon_sysfs_weights_release,
809 	.sysfs_ops = &kobj_sysfs_ops,
810 	.default_groups = damon_sysfs_weights_groups,
811 };
812 
813 /*
814  * quotas directory
815  */
816 
817 struct damon_sysfs_quotas {
818 	struct kobject kobj;
819 	struct damon_sysfs_weights *weights;
820 	unsigned long ms;
821 	unsigned long sz;
822 	unsigned long reset_interval_ms;
823 };
824 
825 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
826 {
827 	return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
828 }
829 
830 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
831 {
832 	struct damon_sysfs_weights *weights;
833 	int err;
834 
835 	weights = damon_sysfs_weights_alloc(0, 0, 0);
836 	if (!weights)
837 		return -ENOMEM;
838 
839 	err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
840 			&quotas->kobj, "weights");
841 	if (err)
842 		kobject_put(&weights->kobj);
843 	else
844 		quotas->weights = weights;
845 	return err;
846 }
847 
848 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
849 {
850 	kobject_put(&quotas->weights->kobj);
851 }
852 
853 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
854 		char *buf)
855 {
856 	struct damon_sysfs_quotas *quotas = container_of(kobj,
857 			struct damon_sysfs_quotas, kobj);
858 
859 	return sysfs_emit(buf, "%lu\n", quotas->ms);
860 }
861 
862 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
863 		const char *buf, size_t count)
864 {
865 	struct damon_sysfs_quotas *quotas = container_of(kobj,
866 			struct damon_sysfs_quotas, kobj);
867 	int err = kstrtoul(buf, 0, &quotas->ms);
868 
869 	if (err)
870 		return -EINVAL;
871 	return count;
872 }
873 
874 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
875 		char *buf)
876 {
877 	struct damon_sysfs_quotas *quotas = container_of(kobj,
878 			struct damon_sysfs_quotas, kobj);
879 
880 	return sysfs_emit(buf, "%lu\n", quotas->sz);
881 }
882 
883 static ssize_t bytes_store(struct kobject *kobj,
884 		struct kobj_attribute *attr, const char *buf, size_t count)
885 {
886 	struct damon_sysfs_quotas *quotas = container_of(kobj,
887 			struct damon_sysfs_quotas, kobj);
888 	int err = kstrtoul(buf, 0, &quotas->sz);
889 
890 	if (err)
891 		return -EINVAL;
892 	return count;
893 }
894 
895 static ssize_t reset_interval_ms_show(struct kobject *kobj,
896 		struct kobj_attribute *attr, char *buf)
897 {
898 	struct damon_sysfs_quotas *quotas = container_of(kobj,
899 			struct damon_sysfs_quotas, kobj);
900 
901 	return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
902 }
903 
904 static ssize_t reset_interval_ms_store(struct kobject *kobj,
905 		struct kobj_attribute *attr, const char *buf, size_t count)
906 {
907 	struct damon_sysfs_quotas *quotas = container_of(kobj,
908 			struct damon_sysfs_quotas, kobj);
909 	int err = kstrtoul(buf, 0, &quotas->reset_interval_ms);
910 
911 	if (err)
912 		return -EINVAL;
913 	return count;
914 }
915 
916 static void damon_sysfs_quotas_release(struct kobject *kobj)
917 {
918 	kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
919 }
920 
921 static struct kobj_attribute damon_sysfs_quotas_ms_attr =
922 		__ATTR_RW_MODE(ms, 0600);
923 
924 static struct kobj_attribute damon_sysfs_quotas_sz_attr =
925 		__ATTR_RW_MODE(bytes, 0600);
926 
927 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
928 		__ATTR_RW_MODE(reset_interval_ms, 0600);
929 
930 static struct attribute *damon_sysfs_quotas_attrs[] = {
931 	&damon_sysfs_quotas_ms_attr.attr,
932 	&damon_sysfs_quotas_sz_attr.attr,
933 	&damon_sysfs_quotas_reset_interval_ms_attr.attr,
934 	NULL,
935 };
936 ATTRIBUTE_GROUPS(damon_sysfs_quotas);
937 
938 static const struct kobj_type damon_sysfs_quotas_ktype = {
939 	.release = damon_sysfs_quotas_release,
940 	.sysfs_ops = &kobj_sysfs_ops,
941 	.default_groups = damon_sysfs_quotas_groups,
942 };
943 
944 /*
945  * access_pattern directory
946  */
947 
948 struct damon_sysfs_access_pattern {
949 	struct kobject kobj;
950 	struct damon_sysfs_ul_range *sz;
951 	struct damon_sysfs_ul_range *nr_accesses;
952 	struct damon_sysfs_ul_range *age;
953 };
954 
955 static
956 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void)
957 {
958 	struct damon_sysfs_access_pattern *access_pattern =
959 		kmalloc(sizeof(*access_pattern), GFP_KERNEL);
960 
961 	if (!access_pattern)
962 		return NULL;
963 	access_pattern->kobj = (struct kobject){};
964 	return access_pattern;
965 }
966 
967 static int damon_sysfs_access_pattern_add_range_dir(
968 		struct damon_sysfs_access_pattern *access_pattern,
969 		struct damon_sysfs_ul_range **range_dir_ptr,
970 		char *name)
971 {
972 	struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0);
973 	int err;
974 
975 	if (!range)
976 		return -ENOMEM;
977 	err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype,
978 			&access_pattern->kobj, name);
979 	if (err)
980 		kobject_put(&range->kobj);
981 	else
982 		*range_dir_ptr = range;
983 	return err;
984 }
985 
986 static int damon_sysfs_access_pattern_add_dirs(
987 		struct damon_sysfs_access_pattern *access_pattern)
988 {
989 	int err;
990 
991 	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
992 			&access_pattern->sz, "sz");
993 	if (err)
994 		goto put_sz_out;
995 
996 	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
997 			&access_pattern->nr_accesses, "nr_accesses");
998 	if (err)
999 		goto put_nr_accesses_sz_out;
1000 
1001 	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1002 			&access_pattern->age, "age");
1003 	if (err)
1004 		goto put_age_nr_accesses_sz_out;
1005 	return 0;
1006 
1007 put_age_nr_accesses_sz_out:
1008 	kobject_put(&access_pattern->age->kobj);
1009 	access_pattern->age = NULL;
1010 put_nr_accesses_sz_out:
1011 	kobject_put(&access_pattern->nr_accesses->kobj);
1012 	access_pattern->nr_accesses = NULL;
1013 put_sz_out:
1014 	kobject_put(&access_pattern->sz->kobj);
1015 	access_pattern->sz = NULL;
1016 	return err;
1017 }
1018 
1019 static void damon_sysfs_access_pattern_rm_dirs(
1020 		struct damon_sysfs_access_pattern *access_pattern)
1021 {
1022 	kobject_put(&access_pattern->sz->kobj);
1023 	kobject_put(&access_pattern->nr_accesses->kobj);
1024 	kobject_put(&access_pattern->age->kobj);
1025 }
1026 
1027 static void damon_sysfs_access_pattern_release(struct kobject *kobj)
1028 {
1029 	kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj));
1030 }
1031 
1032 static struct attribute *damon_sysfs_access_pattern_attrs[] = {
1033 	NULL,
1034 };
1035 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern);
1036 
1037 static const struct kobj_type damon_sysfs_access_pattern_ktype = {
1038 	.release = damon_sysfs_access_pattern_release,
1039 	.sysfs_ops = &kobj_sysfs_ops,
1040 	.default_groups = damon_sysfs_access_pattern_groups,
1041 };
1042 
1043 /*
1044  * scheme directory
1045  */
1046 
1047 struct damon_sysfs_scheme {
1048 	struct kobject kobj;
1049 	enum damos_action action;
1050 	struct damon_sysfs_access_pattern *access_pattern;
1051 	struct damon_sysfs_quotas *quotas;
1052 	struct damon_sysfs_watermarks *watermarks;
1053 	struct damon_sysfs_scheme_filters *filters;
1054 	struct damon_sysfs_stats *stats;
1055 	struct damon_sysfs_scheme_regions *tried_regions;
1056 };
1057 
1058 /* This should match with enum damos_action */
1059 static const char * const damon_sysfs_damos_action_strs[] = {
1060 	"willneed",
1061 	"cold",
1062 	"pageout",
1063 	"hugepage",
1064 	"nohugepage",
1065 	"lru_prio",
1066 	"lru_deprio",
1067 	"stat",
1068 };
1069 
1070 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
1071 		enum damos_action action)
1072 {
1073 	struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme),
1074 				GFP_KERNEL);
1075 
1076 	if (!scheme)
1077 		return NULL;
1078 	scheme->kobj = (struct kobject){};
1079 	scheme->action = action;
1080 	return scheme;
1081 }
1082 
1083 static int damon_sysfs_scheme_set_access_pattern(
1084 		struct damon_sysfs_scheme *scheme)
1085 {
1086 	struct damon_sysfs_access_pattern *access_pattern;
1087 	int err;
1088 
1089 	access_pattern = damon_sysfs_access_pattern_alloc();
1090 	if (!access_pattern)
1091 		return -ENOMEM;
1092 	err = kobject_init_and_add(&access_pattern->kobj,
1093 			&damon_sysfs_access_pattern_ktype, &scheme->kobj,
1094 			"access_pattern");
1095 	if (err)
1096 		goto out;
1097 	err = damon_sysfs_access_pattern_add_dirs(access_pattern);
1098 	if (err)
1099 		goto out;
1100 	scheme->access_pattern = access_pattern;
1101 	return 0;
1102 
1103 out:
1104 	kobject_put(&access_pattern->kobj);
1105 	return err;
1106 }
1107 
1108 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
1109 {
1110 	struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
1111 	int err;
1112 
1113 	if (!quotas)
1114 		return -ENOMEM;
1115 	err = kobject_init_and_add(&quotas->kobj, &damon_sysfs_quotas_ktype,
1116 			&scheme->kobj, "quotas");
1117 	if (err)
1118 		goto out;
1119 	err = damon_sysfs_quotas_add_dirs(quotas);
1120 	if (err)
1121 		goto out;
1122 	scheme->quotas = quotas;
1123 	return 0;
1124 
1125 out:
1126 	kobject_put(&quotas->kobj);
1127 	return err;
1128 }
1129 
1130 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
1131 {
1132 	struct damon_sysfs_watermarks *watermarks =
1133 		damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
1134 	int err;
1135 
1136 	if (!watermarks)
1137 		return -ENOMEM;
1138 	err = kobject_init_and_add(&watermarks->kobj,
1139 			&damon_sysfs_watermarks_ktype, &scheme->kobj,
1140 			"watermarks");
1141 	if (err)
1142 		kobject_put(&watermarks->kobj);
1143 	else
1144 		scheme->watermarks = watermarks;
1145 	return err;
1146 }
1147 
1148 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme)
1149 {
1150 	struct damon_sysfs_scheme_filters *filters =
1151 		damon_sysfs_scheme_filters_alloc();
1152 	int err;
1153 
1154 	if (!filters)
1155 		return -ENOMEM;
1156 	err = kobject_init_and_add(&filters->kobj,
1157 			&damon_sysfs_scheme_filters_ktype, &scheme->kobj,
1158 			"filters");
1159 	if (err)
1160 		kobject_put(&filters->kobj);
1161 	else
1162 		scheme->filters = filters;
1163 	return err;
1164 }
1165 
1166 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme)
1167 {
1168 	struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc();
1169 	int err;
1170 
1171 	if (!stats)
1172 		return -ENOMEM;
1173 	err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype,
1174 			&scheme->kobj, "stats");
1175 	if (err)
1176 		kobject_put(&stats->kobj);
1177 	else
1178 		scheme->stats = stats;
1179 	return err;
1180 }
1181 
1182 static int damon_sysfs_scheme_set_tried_regions(
1183 		struct damon_sysfs_scheme *scheme)
1184 {
1185 	struct damon_sysfs_scheme_regions *tried_regions =
1186 		damon_sysfs_scheme_regions_alloc();
1187 	int err;
1188 
1189 	if (!tried_regions)
1190 		return -ENOMEM;
1191 	err = kobject_init_and_add(&tried_regions->kobj,
1192 			&damon_sysfs_scheme_regions_ktype, &scheme->kobj,
1193 			"tried_regions");
1194 	if (err)
1195 		kobject_put(&tried_regions->kobj);
1196 	else
1197 		scheme->tried_regions = tried_regions;
1198 	return err;
1199 }
1200 
1201 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
1202 {
1203 	int err;
1204 
1205 	err = damon_sysfs_scheme_set_access_pattern(scheme);
1206 	if (err)
1207 		return err;
1208 	err = damon_sysfs_scheme_set_quotas(scheme);
1209 	if (err)
1210 		goto put_access_pattern_out;
1211 	err = damon_sysfs_scheme_set_watermarks(scheme);
1212 	if (err)
1213 		goto put_quotas_access_pattern_out;
1214 	err = damon_sysfs_scheme_set_filters(scheme);
1215 	if (err)
1216 		goto put_watermarks_quotas_access_pattern_out;
1217 	err = damon_sysfs_scheme_set_stats(scheme);
1218 	if (err)
1219 		goto put_filters_watermarks_quotas_access_pattern_out;
1220 	err = damon_sysfs_scheme_set_tried_regions(scheme);
1221 	if (err)
1222 		goto put_tried_regions_out;
1223 	return 0;
1224 
1225 put_tried_regions_out:
1226 	kobject_put(&scheme->tried_regions->kobj);
1227 	scheme->tried_regions = NULL;
1228 put_filters_watermarks_quotas_access_pattern_out:
1229 	kobject_put(&scheme->filters->kobj);
1230 	scheme->filters = NULL;
1231 put_watermarks_quotas_access_pattern_out:
1232 	kobject_put(&scheme->watermarks->kobj);
1233 	scheme->watermarks = NULL;
1234 put_quotas_access_pattern_out:
1235 	kobject_put(&scheme->quotas->kobj);
1236 	scheme->quotas = NULL;
1237 put_access_pattern_out:
1238 	kobject_put(&scheme->access_pattern->kobj);
1239 	scheme->access_pattern = NULL;
1240 	return err;
1241 }
1242 
1243 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
1244 {
1245 	damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
1246 	kobject_put(&scheme->access_pattern->kobj);
1247 	damon_sysfs_quotas_rm_dirs(scheme->quotas);
1248 	kobject_put(&scheme->quotas->kobj);
1249 	kobject_put(&scheme->watermarks->kobj);
1250 	damon_sysfs_scheme_filters_rm_dirs(scheme->filters);
1251 	kobject_put(&scheme->filters->kobj);
1252 	kobject_put(&scheme->stats->kobj);
1253 	damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions);
1254 	kobject_put(&scheme->tried_regions->kobj);
1255 }
1256 
1257 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
1258 		char *buf)
1259 {
1260 	struct damon_sysfs_scheme *scheme = container_of(kobj,
1261 			struct damon_sysfs_scheme, kobj);
1262 
1263 	return sysfs_emit(buf, "%s\n",
1264 			damon_sysfs_damos_action_strs[scheme->action]);
1265 }
1266 
1267 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr,
1268 		const char *buf, size_t count)
1269 {
1270 	struct damon_sysfs_scheme *scheme = container_of(kobj,
1271 			struct damon_sysfs_scheme, kobj);
1272 	enum damos_action action;
1273 
1274 	for (action = 0; action < NR_DAMOS_ACTIONS; action++) {
1275 		if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) {
1276 			scheme->action = action;
1277 			return count;
1278 		}
1279 	}
1280 	return -EINVAL;
1281 }
1282 
1283 static void damon_sysfs_scheme_release(struct kobject *kobj)
1284 {
1285 	kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
1286 }
1287 
1288 static struct kobj_attribute damon_sysfs_scheme_action_attr =
1289 		__ATTR_RW_MODE(action, 0600);
1290 
1291 static struct attribute *damon_sysfs_scheme_attrs[] = {
1292 	&damon_sysfs_scheme_action_attr.attr,
1293 	NULL,
1294 };
1295 ATTRIBUTE_GROUPS(damon_sysfs_scheme);
1296 
1297 static const struct kobj_type damon_sysfs_scheme_ktype = {
1298 	.release = damon_sysfs_scheme_release,
1299 	.sysfs_ops = &kobj_sysfs_ops,
1300 	.default_groups = damon_sysfs_scheme_groups,
1301 };
1302 
1303 /*
1304  * schemes directory
1305  */
1306 
1307 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void)
1308 {
1309 	return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL);
1310 }
1311 
1312 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes)
1313 {
1314 	struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr;
1315 	int i;
1316 
1317 	for (i = 0; i < schemes->nr; i++) {
1318 		damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
1319 		kobject_put(&schemes_arr[i]->kobj);
1320 	}
1321 	schemes->nr = 0;
1322 	kfree(schemes_arr);
1323 	schemes->schemes_arr = NULL;
1324 }
1325 
1326 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes,
1327 		int nr_schemes)
1328 {
1329 	struct damon_sysfs_scheme **schemes_arr, *scheme;
1330 	int err, i;
1331 
1332 	damon_sysfs_schemes_rm_dirs(schemes);
1333 	if (!nr_schemes)
1334 		return 0;
1335 
1336 	schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr),
1337 			GFP_KERNEL | __GFP_NOWARN);
1338 	if (!schemes_arr)
1339 		return -ENOMEM;
1340 	schemes->schemes_arr = schemes_arr;
1341 
1342 	for (i = 0; i < nr_schemes; i++) {
1343 		scheme = damon_sysfs_scheme_alloc(DAMOS_STAT);
1344 		if (!scheme) {
1345 			damon_sysfs_schemes_rm_dirs(schemes);
1346 			return -ENOMEM;
1347 		}
1348 
1349 		err = kobject_init_and_add(&scheme->kobj,
1350 				&damon_sysfs_scheme_ktype, &schemes->kobj,
1351 				"%d", i);
1352 		if (err)
1353 			goto out;
1354 		err = damon_sysfs_scheme_add_dirs(scheme);
1355 		if (err)
1356 			goto out;
1357 
1358 		schemes_arr[i] = scheme;
1359 		schemes->nr++;
1360 	}
1361 	return 0;
1362 
1363 out:
1364 	damon_sysfs_schemes_rm_dirs(schemes);
1365 	kobject_put(&scheme->kobj);
1366 	return err;
1367 }
1368 
1369 static ssize_t nr_schemes_show(struct kobject *kobj,
1370 		struct kobj_attribute *attr, char *buf)
1371 {
1372 	struct damon_sysfs_schemes *schemes = container_of(kobj,
1373 			struct damon_sysfs_schemes, kobj);
1374 
1375 	return sysfs_emit(buf, "%d\n", schemes->nr);
1376 }
1377 
1378 static ssize_t nr_schemes_store(struct kobject *kobj,
1379 		struct kobj_attribute *attr, const char *buf, size_t count)
1380 {
1381 	struct damon_sysfs_schemes *schemes;
1382 	int nr, err = kstrtoint(buf, 0, &nr);
1383 
1384 	if (err)
1385 		return err;
1386 	if (nr < 0)
1387 		return -EINVAL;
1388 
1389 	schemes = container_of(kobj, struct damon_sysfs_schemes, kobj);
1390 
1391 	if (!mutex_trylock(&damon_sysfs_lock))
1392 		return -EBUSY;
1393 	err = damon_sysfs_schemes_add_dirs(schemes, nr);
1394 	mutex_unlock(&damon_sysfs_lock);
1395 	if (err)
1396 		return err;
1397 	return count;
1398 }
1399 
1400 static void damon_sysfs_schemes_release(struct kobject *kobj)
1401 {
1402 	kfree(container_of(kobj, struct damon_sysfs_schemes, kobj));
1403 }
1404 
1405 static struct kobj_attribute damon_sysfs_schemes_nr_attr =
1406 		__ATTR_RW_MODE(nr_schemes, 0600);
1407 
1408 static struct attribute *damon_sysfs_schemes_attrs[] = {
1409 	&damon_sysfs_schemes_nr_attr.attr,
1410 	NULL,
1411 };
1412 ATTRIBUTE_GROUPS(damon_sysfs_schemes);
1413 
1414 const struct kobj_type damon_sysfs_schemes_ktype = {
1415 	.release = damon_sysfs_schemes_release,
1416 	.sysfs_ops = &kobj_sysfs_ops,
1417 	.default_groups = damon_sysfs_schemes_groups,
1418 };
1419 
1420 static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg,
1421 		char *memcg_path_buf, char *path)
1422 {
1423 #ifdef CONFIG_MEMCG
1424 	cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX);
1425 	if (sysfs_streq(memcg_path_buf, path))
1426 		return true;
1427 #endif /* CONFIG_MEMCG */
1428 	return false;
1429 }
1430 
1431 static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id)
1432 {
1433 	struct mem_cgroup *memcg;
1434 	char *path;
1435 	bool found = false;
1436 
1437 	if (!memcg_path)
1438 		return -EINVAL;
1439 
1440 	path = kmalloc(sizeof(*path) * PATH_MAX, GFP_KERNEL);
1441 	if (!path)
1442 		return -ENOMEM;
1443 
1444 	for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg;
1445 			memcg = mem_cgroup_iter(NULL, memcg, NULL)) {
1446 		/* skip removed memcg */
1447 		if (!mem_cgroup_id(memcg))
1448 			continue;
1449 		if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) {
1450 			*id = mem_cgroup_id(memcg);
1451 			found = true;
1452 			break;
1453 		}
1454 	}
1455 
1456 	kfree(path);
1457 	return found ? 0 : -EINVAL;
1458 }
1459 
1460 static int damon_sysfs_set_scheme_filters(struct damos *scheme,
1461 		struct damon_sysfs_scheme_filters *sysfs_filters)
1462 {
1463 	int i;
1464 	struct damos_filter *filter, *next;
1465 
1466 	damos_for_each_filter_safe(filter, next, scheme)
1467 		damos_destroy_filter(filter);
1468 
1469 	for (i = 0; i < sysfs_filters->nr; i++) {
1470 		struct damon_sysfs_scheme_filter *sysfs_filter =
1471 			sysfs_filters->filters_arr[i];
1472 		struct damos_filter *filter =
1473 			damos_new_filter(sysfs_filter->type,
1474 					sysfs_filter->matching);
1475 		int err;
1476 
1477 		if (!filter)
1478 			return -ENOMEM;
1479 		if (filter->type == DAMOS_FILTER_TYPE_MEMCG) {
1480 			err = damon_sysfs_memcg_path_to_id(
1481 					sysfs_filter->memcg_path,
1482 					&filter->memcg_id);
1483 			if (err) {
1484 				damos_destroy_filter(filter);
1485 				return err;
1486 			}
1487 		}
1488 		damos_add_filter(scheme, filter);
1489 	}
1490 	return 0;
1491 }
1492 
1493 static struct damos *damon_sysfs_mk_scheme(
1494 		struct damon_sysfs_scheme *sysfs_scheme)
1495 {
1496 	struct damon_sysfs_access_pattern *access_pattern =
1497 		sysfs_scheme->access_pattern;
1498 	struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1499 	struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1500 	struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1501 	struct damon_sysfs_scheme_filters *sysfs_filters =
1502 		sysfs_scheme->filters;
1503 	struct damos *scheme;
1504 	int err;
1505 
1506 	struct damos_access_pattern pattern = {
1507 		.min_sz_region = access_pattern->sz->min,
1508 		.max_sz_region = access_pattern->sz->max,
1509 		.min_nr_accesses = access_pattern->nr_accesses->min,
1510 		.max_nr_accesses = access_pattern->nr_accesses->max,
1511 		.min_age_region = access_pattern->age->min,
1512 		.max_age_region = access_pattern->age->max,
1513 	};
1514 	struct damos_quota quota = {
1515 		.ms = sysfs_quotas->ms,
1516 		.sz = sysfs_quotas->sz,
1517 		.reset_interval = sysfs_quotas->reset_interval_ms,
1518 		.weight_sz = sysfs_weights->sz,
1519 		.weight_nr_accesses = sysfs_weights->nr_accesses,
1520 		.weight_age = sysfs_weights->age,
1521 	};
1522 	struct damos_watermarks wmarks = {
1523 		.metric = sysfs_wmarks->metric,
1524 		.interval = sysfs_wmarks->interval_us,
1525 		.high = sysfs_wmarks->high,
1526 		.mid = sysfs_wmarks->mid,
1527 		.low = sysfs_wmarks->low,
1528 	};
1529 
1530 	scheme = damon_new_scheme(&pattern, sysfs_scheme->action, &quota,
1531 			&wmarks);
1532 	if (!scheme)
1533 		return NULL;
1534 
1535 	err = damon_sysfs_set_scheme_filters(scheme, sysfs_filters);
1536 	if (err) {
1537 		damon_destroy_scheme(scheme);
1538 		return NULL;
1539 	}
1540 	return scheme;
1541 }
1542 
1543 static void damon_sysfs_update_scheme(struct damos *scheme,
1544 		struct damon_sysfs_scheme *sysfs_scheme)
1545 {
1546 	struct damon_sysfs_access_pattern *access_pattern =
1547 		sysfs_scheme->access_pattern;
1548 	struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1549 	struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1550 	struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1551 	int err;
1552 
1553 	scheme->pattern.min_sz_region = access_pattern->sz->min;
1554 	scheme->pattern.max_sz_region = access_pattern->sz->max;
1555 	scheme->pattern.min_nr_accesses = access_pattern->nr_accesses->min;
1556 	scheme->pattern.max_nr_accesses = access_pattern->nr_accesses->max;
1557 	scheme->pattern.min_age_region = access_pattern->age->min;
1558 	scheme->pattern.max_age_region = access_pattern->age->max;
1559 
1560 	scheme->action = sysfs_scheme->action;
1561 
1562 	scheme->quota.ms = sysfs_quotas->ms;
1563 	scheme->quota.sz = sysfs_quotas->sz;
1564 	scheme->quota.reset_interval = sysfs_quotas->reset_interval_ms;
1565 	scheme->quota.weight_sz = sysfs_weights->sz;
1566 	scheme->quota.weight_nr_accesses = sysfs_weights->nr_accesses;
1567 	scheme->quota.weight_age = sysfs_weights->age;
1568 
1569 	scheme->wmarks.metric = sysfs_wmarks->metric;
1570 	scheme->wmarks.interval = sysfs_wmarks->interval_us;
1571 	scheme->wmarks.high = sysfs_wmarks->high;
1572 	scheme->wmarks.mid = sysfs_wmarks->mid;
1573 	scheme->wmarks.low = sysfs_wmarks->low;
1574 
1575 	err = damon_sysfs_set_scheme_filters(scheme, sysfs_scheme->filters);
1576 	if (err)
1577 		damon_destroy_scheme(scheme);
1578 }
1579 
1580 int damon_sysfs_set_schemes(struct damon_ctx *ctx,
1581 		struct damon_sysfs_schemes *sysfs_schemes)
1582 {
1583 	struct damos *scheme, *next;
1584 	int i = 0;
1585 
1586 	damon_for_each_scheme_safe(scheme, next, ctx) {
1587 		if (i < sysfs_schemes->nr)
1588 			damon_sysfs_update_scheme(scheme,
1589 					sysfs_schemes->schemes_arr[i]);
1590 		else
1591 			damon_destroy_scheme(scheme);
1592 		i++;
1593 	}
1594 
1595 	for (; i < sysfs_schemes->nr; i++) {
1596 		struct damos *scheme, *next;
1597 
1598 		scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]);
1599 		if (!scheme) {
1600 			damon_for_each_scheme_safe(scheme, next, ctx)
1601 				damon_destroy_scheme(scheme);
1602 			return -ENOMEM;
1603 		}
1604 		damon_add_scheme(ctx, scheme);
1605 	}
1606 	return 0;
1607 }
1608 
1609 void damon_sysfs_schemes_update_stats(
1610 		struct damon_sysfs_schemes *sysfs_schemes,
1611 		struct damon_ctx *ctx)
1612 {
1613 	struct damos *scheme;
1614 	int schemes_idx = 0;
1615 
1616 	damon_for_each_scheme(scheme, ctx) {
1617 		struct damon_sysfs_stats *sysfs_stats;
1618 
1619 		/* user could have removed the scheme sysfs dir */
1620 		if (schemes_idx >= sysfs_schemes->nr)
1621 			break;
1622 
1623 		sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats;
1624 		sysfs_stats->nr_tried = scheme->stat.nr_tried;
1625 		sysfs_stats->sz_tried = scheme->stat.sz_tried;
1626 		sysfs_stats->nr_applied = scheme->stat.nr_applied;
1627 		sysfs_stats->sz_applied = scheme->stat.sz_applied;
1628 		sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds;
1629 	}
1630 }
1631 
1632 /*
1633  * damon_sysfs_schemes that need to update its schemes regions dir.  Protected
1634  * by damon_sysfs_lock
1635  */
1636 static struct damon_sysfs_schemes *damon_sysfs_schemes_for_damos_callback;
1637 static int damon_sysfs_schemes_region_idx;
1638 static bool damos_regions_upd_total_bytes_only;
1639 
1640 /*
1641  * DAMON callback that called before damos apply.  While this callback is
1642  * registered, damon_sysfs_lock should be held to ensure the regions
1643  * directories exist.
1644  */
1645 static int damon_sysfs_before_damos_apply(struct damon_ctx *ctx,
1646 		struct damon_target *t, struct damon_region *r,
1647 		struct damos *s)
1648 {
1649 	struct damos *scheme;
1650 	struct damon_sysfs_scheme_regions *sysfs_regions;
1651 	struct damon_sysfs_scheme_region *region;
1652 	struct damon_sysfs_schemes *sysfs_schemes =
1653 		damon_sysfs_schemes_for_damos_callback;
1654 	int schemes_idx = 0;
1655 
1656 	damon_for_each_scheme(scheme, ctx) {
1657 		if (scheme == s)
1658 			break;
1659 		schemes_idx++;
1660 	}
1661 
1662 	/* user could have removed the scheme sysfs dir */
1663 	if (schemes_idx >= sysfs_schemes->nr)
1664 		return 0;
1665 
1666 	sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions;
1667 	sysfs_regions->total_bytes += r->ar.end - r->ar.start;
1668 	if (damos_regions_upd_total_bytes_only)
1669 		return 0;
1670 
1671 	region = damon_sysfs_scheme_region_alloc(r);
1672 	list_add_tail(&region->list, &sysfs_regions->regions_list);
1673 	sysfs_regions->nr_regions++;
1674 	if (kobject_init_and_add(&region->kobj,
1675 				&damon_sysfs_scheme_region_ktype,
1676 				&sysfs_regions->kobj, "%d",
1677 				damon_sysfs_schemes_region_idx++)) {
1678 		kobject_put(&region->kobj);
1679 	}
1680 	return 0;
1681 }
1682 
1683 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1684 int damon_sysfs_schemes_clear_regions(
1685 		struct damon_sysfs_schemes *sysfs_schemes,
1686 		struct damon_ctx *ctx)
1687 {
1688 	struct damos *scheme;
1689 	int schemes_idx = 0;
1690 
1691 	damon_for_each_scheme(scheme, ctx) {
1692 		struct damon_sysfs_scheme *sysfs_scheme;
1693 
1694 		/* user could have removed the scheme sysfs dir */
1695 		if (schemes_idx >= sysfs_schemes->nr)
1696 			break;
1697 
1698 		sysfs_scheme = sysfs_schemes->schemes_arr[schemes_idx++];
1699 		damon_sysfs_scheme_regions_rm_dirs(
1700 				sysfs_scheme->tried_regions);
1701 		sysfs_scheme->tried_regions->total_bytes = 0;
1702 	}
1703 	return 0;
1704 }
1705 
1706 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1707 int damon_sysfs_schemes_update_regions_start(
1708 		struct damon_sysfs_schemes *sysfs_schemes,
1709 		struct damon_ctx *ctx, bool total_bytes_only)
1710 {
1711 	damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx);
1712 	damon_sysfs_schemes_for_damos_callback = sysfs_schemes;
1713 	damos_regions_upd_total_bytes_only = total_bytes_only;
1714 	ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply;
1715 	return 0;
1716 }
1717 
1718 /*
1719  * Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock.  Caller
1720  * should unlock damon_sysfs_lock which held before
1721  * damon_sysfs_schemes_update_regions_start()
1722  */
1723 int damon_sysfs_schemes_update_regions_stop(struct damon_ctx *ctx)
1724 {
1725 	damon_sysfs_schemes_for_damos_callback = NULL;
1726 	ctx->callback.before_damos_apply = NULL;
1727 	damon_sysfs_schemes_region_idx = 0;
1728 	return 0;
1729 }
1730