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