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