xref: /linux/mm/damon/sysfs-schemes.c (revision 9c5968db9e625019a0ee5226c7eebef5519d366a)
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 #include <linux/numa.h>
10 
11 #include "sysfs-common.h"
12 
13 /*
14  * scheme region directory
15  */
16 
17 struct damon_sysfs_scheme_region {
18 	struct kobject kobj;
19 	struct damon_addr_range ar;
20 	unsigned int nr_accesses;
21 	unsigned int age;
22 	unsigned long sz_filter_passed;
23 	struct list_head list;
24 };
25 
26 static struct damon_sysfs_scheme_region *damon_sysfs_scheme_region_alloc(
27 		struct damon_region *region)
28 {
29 	struct damon_sysfs_scheme_region *sysfs_region = kmalloc(
30 			sizeof(*sysfs_region), GFP_KERNEL);
31 
32 	if (!sysfs_region)
33 		return NULL;
34 	sysfs_region->kobj = (struct kobject){};
35 	sysfs_region->ar = region->ar;
36 	sysfs_region->nr_accesses = region->nr_accesses_bp / 10000;
37 	sysfs_region->age = region->age;
38 	INIT_LIST_HEAD(&sysfs_region->list);
39 	return sysfs_region;
40 }
41 
42 static ssize_t start_show(struct kobject *kobj, struct kobj_attribute *attr,
43 		char *buf)
44 {
45 	struct damon_sysfs_scheme_region *region = container_of(kobj,
46 			struct damon_sysfs_scheme_region, kobj);
47 
48 	return sysfs_emit(buf, "%lu\n", region->ar.start);
49 }
50 
51 static ssize_t end_show(struct kobject *kobj, struct kobj_attribute *attr,
52 		char *buf)
53 {
54 	struct damon_sysfs_scheme_region *region = container_of(kobj,
55 			struct damon_sysfs_scheme_region, kobj);
56 
57 	return sysfs_emit(buf, "%lu\n", region->ar.end);
58 }
59 
60 static ssize_t nr_accesses_show(struct kobject *kobj,
61 		struct kobj_attribute *attr, char *buf)
62 {
63 	struct damon_sysfs_scheme_region *region = container_of(kobj,
64 			struct damon_sysfs_scheme_region, kobj);
65 
66 	return sysfs_emit(buf, "%u\n", region->nr_accesses);
67 }
68 
69 static ssize_t age_show(struct kobject *kobj, struct kobj_attribute *attr,
70 		char *buf)
71 {
72 	struct damon_sysfs_scheme_region *region = container_of(kobj,
73 			struct damon_sysfs_scheme_region, kobj);
74 
75 	return sysfs_emit(buf, "%u\n", region->age);
76 }
77 
78 static ssize_t sz_filter_passed_show(struct kobject *kobj,
79 		struct kobj_attribute *attr, char *buf)
80 {
81 	struct damon_sysfs_scheme_region *region = container_of(kobj,
82 			struct damon_sysfs_scheme_region, kobj);
83 
84 	return sysfs_emit(buf, "%lu\n", region->sz_filter_passed);
85 }
86 
87 static void damon_sysfs_scheme_region_release(struct kobject *kobj)
88 {
89 	struct damon_sysfs_scheme_region *region = container_of(kobj,
90 			struct damon_sysfs_scheme_region, kobj);
91 
92 	list_del(&region->list);
93 	kfree(region);
94 }
95 
96 static struct kobj_attribute damon_sysfs_scheme_region_start_attr =
97 		__ATTR_RO_MODE(start, 0400);
98 
99 static struct kobj_attribute damon_sysfs_scheme_region_end_attr =
100 		__ATTR_RO_MODE(end, 0400);
101 
102 static struct kobj_attribute damon_sysfs_scheme_region_nr_accesses_attr =
103 		__ATTR_RO_MODE(nr_accesses, 0400);
104 
105 static struct kobj_attribute damon_sysfs_scheme_region_age_attr =
106 		__ATTR_RO_MODE(age, 0400);
107 
108 static struct kobj_attribute damon_sysfs_scheme_region_sz_filter_passed_attr =
109 		__ATTR_RO_MODE(sz_filter_passed, 0400);
110 
111 static struct attribute *damon_sysfs_scheme_region_attrs[] = {
112 	&damon_sysfs_scheme_region_start_attr.attr,
113 	&damon_sysfs_scheme_region_end_attr.attr,
114 	&damon_sysfs_scheme_region_nr_accesses_attr.attr,
115 	&damon_sysfs_scheme_region_age_attr.attr,
116 	&damon_sysfs_scheme_region_sz_filter_passed_attr.attr,
117 	NULL,
118 };
119 ATTRIBUTE_GROUPS(damon_sysfs_scheme_region);
120 
121 static const struct kobj_type damon_sysfs_scheme_region_ktype = {
122 	.release = damon_sysfs_scheme_region_release,
123 	.sysfs_ops = &kobj_sysfs_ops,
124 	.default_groups = damon_sysfs_scheme_region_groups,
125 };
126 
127 /*
128  * scheme regions directory
129  */
130 
131 struct damon_sysfs_scheme_regions {
132 	struct kobject kobj;
133 	struct list_head regions_list;
134 	int nr_regions;
135 	unsigned long total_bytes;
136 };
137 
138 static struct damon_sysfs_scheme_regions *
139 damon_sysfs_scheme_regions_alloc(void)
140 {
141 	struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions),
142 			GFP_KERNEL);
143 
144 	if (!regions)
145 		return NULL;
146 
147 	regions->kobj = (struct kobject){};
148 	INIT_LIST_HEAD(&regions->regions_list);
149 	regions->nr_regions = 0;
150 	regions->total_bytes = 0;
151 	return regions;
152 }
153 
154 static ssize_t total_bytes_show(struct kobject *kobj,
155 		struct kobj_attribute *attr, char *buf)
156 {
157 	struct damon_sysfs_scheme_regions *regions = container_of(kobj,
158 			struct damon_sysfs_scheme_regions, kobj);
159 
160 	return sysfs_emit(buf, "%lu\n", regions->total_bytes);
161 }
162 
163 static void damon_sysfs_scheme_regions_rm_dirs(
164 		struct damon_sysfs_scheme_regions *regions)
165 {
166 	struct damon_sysfs_scheme_region *r, *next;
167 
168 	list_for_each_entry_safe(r, next, &regions->regions_list, list) {
169 		/* release function deletes it from the list */
170 		kobject_put(&r->kobj);
171 		regions->nr_regions--;
172 	}
173 }
174 
175 static void damon_sysfs_scheme_regions_release(struct kobject *kobj)
176 {
177 	kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj));
178 }
179 
180 static struct kobj_attribute damon_sysfs_scheme_regions_total_bytes_attr =
181 		__ATTR_RO_MODE(total_bytes, 0400);
182 
183 static struct attribute *damon_sysfs_scheme_regions_attrs[] = {
184 	&damon_sysfs_scheme_regions_total_bytes_attr.attr,
185 	NULL,
186 };
187 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions);
188 
189 static const struct kobj_type damon_sysfs_scheme_regions_ktype = {
190 	.release = damon_sysfs_scheme_regions_release,
191 	.sysfs_ops = &kobj_sysfs_ops,
192 	.default_groups = damon_sysfs_scheme_regions_groups,
193 };
194 
195 /*
196  * schemes/stats directory
197  */
198 
199 struct damon_sysfs_stats {
200 	struct kobject kobj;
201 	unsigned long nr_tried;
202 	unsigned long sz_tried;
203 	unsigned long nr_applied;
204 	unsigned long sz_applied;
205 	unsigned long sz_ops_filter_passed;
206 	unsigned long qt_exceeds;
207 };
208 
209 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void)
210 {
211 	return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL);
212 }
213 
214 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
215 		char *buf)
216 {
217 	struct damon_sysfs_stats *stats = container_of(kobj,
218 			struct damon_sysfs_stats, kobj);
219 
220 	return sysfs_emit(buf, "%lu\n", stats->nr_tried);
221 }
222 
223 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
224 		char *buf)
225 {
226 	struct damon_sysfs_stats *stats = container_of(kobj,
227 			struct damon_sysfs_stats, kobj);
228 
229 	return sysfs_emit(buf, "%lu\n", stats->sz_tried);
230 }
231 
232 static ssize_t nr_applied_show(struct kobject *kobj,
233 		struct kobj_attribute *attr, char *buf)
234 {
235 	struct damon_sysfs_stats *stats = container_of(kobj,
236 			struct damon_sysfs_stats, kobj);
237 
238 	return sysfs_emit(buf, "%lu\n", stats->nr_applied);
239 }
240 
241 static ssize_t sz_applied_show(struct kobject *kobj,
242 		struct kobj_attribute *attr, char *buf)
243 {
244 	struct damon_sysfs_stats *stats = container_of(kobj,
245 			struct damon_sysfs_stats, kobj);
246 
247 	return sysfs_emit(buf, "%lu\n", stats->sz_applied);
248 }
249 
250 static ssize_t sz_ops_filter_passed_show(struct kobject *kobj,
251 		struct kobj_attribute *attr, char *buf)
252 {
253 	struct damon_sysfs_stats *stats = container_of(kobj,
254 			struct damon_sysfs_stats, kobj);
255 
256 	return sysfs_emit(buf, "%lu\n", stats->sz_ops_filter_passed);
257 }
258 
259 static ssize_t qt_exceeds_show(struct kobject *kobj,
260 		struct kobj_attribute *attr, char *buf)
261 {
262 	struct damon_sysfs_stats *stats = container_of(kobj,
263 			struct damon_sysfs_stats, kobj);
264 
265 	return sysfs_emit(buf, "%lu\n", stats->qt_exceeds);
266 }
267 
268 static void damon_sysfs_stats_release(struct kobject *kobj)
269 {
270 	kfree(container_of(kobj, struct damon_sysfs_stats, kobj));
271 }
272 
273 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr =
274 		__ATTR_RO_MODE(nr_tried, 0400);
275 
276 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr =
277 		__ATTR_RO_MODE(sz_tried, 0400);
278 
279 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr =
280 		__ATTR_RO_MODE(nr_applied, 0400);
281 
282 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr =
283 		__ATTR_RO_MODE(sz_applied, 0400);
284 
285 static struct kobj_attribute damon_sysfs_stats_sz_ops_filter_passed_attr =
286 		__ATTR_RO_MODE(sz_ops_filter_passed, 0400);
287 
288 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr =
289 		__ATTR_RO_MODE(qt_exceeds, 0400);
290 
291 static struct attribute *damon_sysfs_stats_attrs[] = {
292 	&damon_sysfs_stats_nr_tried_attr.attr,
293 	&damon_sysfs_stats_sz_tried_attr.attr,
294 	&damon_sysfs_stats_nr_applied_attr.attr,
295 	&damon_sysfs_stats_sz_applied_attr.attr,
296 	&damon_sysfs_stats_sz_ops_filter_passed_attr.attr,
297 	&damon_sysfs_stats_qt_exceeds_attr.attr,
298 	NULL,
299 };
300 ATTRIBUTE_GROUPS(damon_sysfs_stats);
301 
302 static const struct kobj_type damon_sysfs_stats_ktype = {
303 	.release = damon_sysfs_stats_release,
304 	.sysfs_ops = &kobj_sysfs_ops,
305 	.default_groups = damon_sysfs_stats_groups,
306 };
307 
308 /*
309  * filter directory
310  */
311 
312 struct damon_sysfs_scheme_filter {
313 	struct kobject kobj;
314 	enum damos_filter_type type;
315 	bool matching;
316 	bool allow;
317 	char *memcg_path;
318 	struct damon_addr_range addr_range;
319 	int target_idx;
320 };
321 
322 static struct damon_sysfs_scheme_filter *damon_sysfs_scheme_filter_alloc(void)
323 {
324 	return kzalloc(sizeof(struct damon_sysfs_scheme_filter), GFP_KERNEL);
325 }
326 
327 /* Should match with enum damos_filter_type */
328 static const char * const damon_sysfs_scheme_filter_type_strs[] = {
329 	"anon",
330 	"memcg",
331 	"young",
332 	"addr",
333 	"target",
334 };
335 
336 static ssize_t type_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 			damon_sysfs_scheme_filter_type_strs[filter->type]);
344 }
345 
346 static ssize_t type_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 	enum damos_filter_type type;
352 	ssize_t ret = -EINVAL;
353 
354 	for (type = 0; type < NR_DAMOS_FILTER_TYPES; type++) {
355 		if (sysfs_streq(buf, damon_sysfs_scheme_filter_type_strs[
356 					type])) {
357 			filter->type = type;
358 			ret = count;
359 			break;
360 		}
361 	}
362 	return ret;
363 }
364 
365 static ssize_t matching_show(struct kobject *kobj,
366 		struct kobj_attribute *attr, char *buf)
367 {
368 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
369 			struct damon_sysfs_scheme_filter, kobj);
370 
371 	return sysfs_emit(buf, "%c\n", filter->matching ? 'Y' : 'N');
372 }
373 
374 static ssize_t matching_store(struct kobject *kobj,
375 		struct kobj_attribute *attr, const char *buf, size_t count)
376 {
377 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
378 			struct damon_sysfs_scheme_filter, kobj);
379 	bool matching;
380 	int err = kstrtobool(buf, &matching);
381 
382 	if (err)
383 		return err;
384 
385 	filter->matching = matching;
386 	return count;
387 }
388 
389 static ssize_t allow_show(struct kobject *kobj,
390 		struct kobj_attribute *attr, char *buf)
391 {
392 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
393 			struct damon_sysfs_scheme_filter, kobj);
394 
395 	return sysfs_emit(buf, "%c\n", filter->allow ? 'Y' : 'N');
396 }
397 
398 static ssize_t allow_store(struct kobject *kobj,
399 		struct kobj_attribute *attr, const char *buf, size_t count)
400 {
401 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
402 			struct damon_sysfs_scheme_filter, kobj);
403 	bool allow;
404 	int err = kstrtobool(buf, &allow);
405 
406 	if (err)
407 		return err;
408 
409 	filter->allow = allow;
410 	return count;
411 }
412 
413 static ssize_t memcg_path_show(struct kobject *kobj,
414 		struct kobj_attribute *attr, char *buf)
415 {
416 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
417 			struct damon_sysfs_scheme_filter, kobj);
418 
419 	return sysfs_emit(buf, "%s\n",
420 			filter->memcg_path ? filter->memcg_path : "");
421 }
422 
423 static ssize_t memcg_path_store(struct kobject *kobj,
424 		struct kobj_attribute *attr, const char *buf, size_t count)
425 {
426 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
427 			struct damon_sysfs_scheme_filter, kobj);
428 	char *path = kmalloc(sizeof(*path) * (count + 1), GFP_KERNEL);
429 
430 	if (!path)
431 		return -ENOMEM;
432 
433 	strscpy(path, buf, count + 1);
434 	filter->memcg_path = path;
435 	return count;
436 }
437 
438 static ssize_t addr_start_show(struct kobject *kobj,
439 		struct kobj_attribute *attr, char *buf)
440 {
441 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
442 			struct damon_sysfs_scheme_filter, kobj);
443 
444 	return sysfs_emit(buf, "%lu\n", filter->addr_range.start);
445 }
446 
447 static ssize_t addr_start_store(struct kobject *kobj,
448 		struct kobj_attribute *attr, const char *buf, size_t count)
449 {
450 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
451 			struct damon_sysfs_scheme_filter, kobj);
452 	int err = kstrtoul(buf, 0, &filter->addr_range.start);
453 
454 	return err ? err : count;
455 }
456 
457 static ssize_t addr_end_show(struct kobject *kobj,
458 		struct kobj_attribute *attr, char *buf)
459 {
460 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
461 			struct damon_sysfs_scheme_filter, kobj);
462 
463 	return sysfs_emit(buf, "%lu\n", filter->addr_range.end);
464 }
465 
466 static ssize_t addr_end_store(struct kobject *kobj,
467 		struct kobj_attribute *attr, const char *buf, size_t count)
468 {
469 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
470 			struct damon_sysfs_scheme_filter, kobj);
471 	int err = kstrtoul(buf, 0, &filter->addr_range.end);
472 
473 	return err ? err : count;
474 }
475 
476 static ssize_t damon_target_idx_show(struct kobject *kobj,
477 		struct kobj_attribute *attr, char *buf)
478 {
479 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
480 			struct damon_sysfs_scheme_filter, kobj);
481 
482 	return sysfs_emit(buf, "%d\n", filter->target_idx);
483 }
484 
485 static ssize_t damon_target_idx_store(struct kobject *kobj,
486 		struct kobj_attribute *attr, const char *buf, size_t count)
487 {
488 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
489 			struct damon_sysfs_scheme_filter, kobj);
490 	int err = kstrtoint(buf, 0, &filter->target_idx);
491 
492 	return err ? err : count;
493 }
494 
495 static void damon_sysfs_scheme_filter_release(struct kobject *kobj)
496 {
497 	struct damon_sysfs_scheme_filter *filter = container_of(kobj,
498 			struct damon_sysfs_scheme_filter, kobj);
499 
500 	kfree(filter->memcg_path);
501 	kfree(filter);
502 }
503 
504 static struct kobj_attribute damon_sysfs_scheme_filter_type_attr =
505 		__ATTR_RW_MODE(type, 0600);
506 
507 static struct kobj_attribute damon_sysfs_scheme_filter_matching_attr =
508 		__ATTR_RW_MODE(matching, 0600);
509 
510 static struct kobj_attribute damon_sysfs_scheme_filter_allow_attr =
511 		__ATTR_RW_MODE(allow, 0600);
512 
513 static struct kobj_attribute damon_sysfs_scheme_filter_memcg_path_attr =
514 		__ATTR_RW_MODE(memcg_path, 0600);
515 
516 static struct kobj_attribute damon_sysfs_scheme_filter_addr_start_attr =
517 		__ATTR_RW_MODE(addr_start, 0600);
518 
519 static struct kobj_attribute damon_sysfs_scheme_filter_addr_end_attr =
520 		__ATTR_RW_MODE(addr_end, 0600);
521 
522 static struct kobj_attribute damon_sysfs_scheme_filter_damon_target_idx_attr =
523 		__ATTR_RW_MODE(damon_target_idx, 0600);
524 
525 static struct attribute *damon_sysfs_scheme_filter_attrs[] = {
526 	&damon_sysfs_scheme_filter_type_attr.attr,
527 	&damon_sysfs_scheme_filter_matching_attr.attr,
528 	&damon_sysfs_scheme_filter_allow_attr.attr,
529 	&damon_sysfs_scheme_filter_memcg_path_attr.attr,
530 	&damon_sysfs_scheme_filter_addr_start_attr.attr,
531 	&damon_sysfs_scheme_filter_addr_end_attr.attr,
532 	&damon_sysfs_scheme_filter_damon_target_idx_attr.attr,
533 	NULL,
534 };
535 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filter);
536 
537 static const struct kobj_type damon_sysfs_scheme_filter_ktype = {
538 	.release = damon_sysfs_scheme_filter_release,
539 	.sysfs_ops = &kobj_sysfs_ops,
540 	.default_groups = damon_sysfs_scheme_filter_groups,
541 };
542 
543 /*
544  * filters directory
545  */
546 
547 struct damon_sysfs_scheme_filters {
548 	struct kobject kobj;
549 	struct damon_sysfs_scheme_filter **filters_arr;
550 	int nr;
551 };
552 
553 static struct damon_sysfs_scheme_filters *
554 damon_sysfs_scheme_filters_alloc(void)
555 {
556 	return kzalloc(sizeof(struct damon_sysfs_scheme_filters), GFP_KERNEL);
557 }
558 
559 static void damon_sysfs_scheme_filters_rm_dirs(
560 		struct damon_sysfs_scheme_filters *filters)
561 {
562 	struct damon_sysfs_scheme_filter **filters_arr = filters->filters_arr;
563 	int i;
564 
565 	for (i = 0; i < filters->nr; i++)
566 		kobject_put(&filters_arr[i]->kobj);
567 	filters->nr = 0;
568 	kfree(filters_arr);
569 	filters->filters_arr = NULL;
570 }
571 
572 static int damon_sysfs_scheme_filters_add_dirs(
573 		struct damon_sysfs_scheme_filters *filters, int nr_filters)
574 {
575 	struct damon_sysfs_scheme_filter **filters_arr, *filter;
576 	int err, i;
577 
578 	damon_sysfs_scheme_filters_rm_dirs(filters);
579 	if (!nr_filters)
580 		return 0;
581 
582 	filters_arr = kmalloc_array(nr_filters, sizeof(*filters_arr),
583 			GFP_KERNEL | __GFP_NOWARN);
584 	if (!filters_arr)
585 		return -ENOMEM;
586 	filters->filters_arr = filters_arr;
587 
588 	for (i = 0; i < nr_filters; i++) {
589 		filter = damon_sysfs_scheme_filter_alloc();
590 		if (!filter) {
591 			damon_sysfs_scheme_filters_rm_dirs(filters);
592 			return -ENOMEM;
593 		}
594 
595 		err = kobject_init_and_add(&filter->kobj,
596 				&damon_sysfs_scheme_filter_ktype,
597 				&filters->kobj, "%d", i);
598 		if (err) {
599 			kobject_put(&filter->kobj);
600 			damon_sysfs_scheme_filters_rm_dirs(filters);
601 			return err;
602 		}
603 
604 		filters_arr[i] = filter;
605 		filters->nr++;
606 	}
607 	return 0;
608 }
609 
610 static ssize_t nr_filters_show(struct kobject *kobj,
611 		struct kobj_attribute *attr, char *buf)
612 {
613 	struct damon_sysfs_scheme_filters *filters = container_of(kobj,
614 			struct damon_sysfs_scheme_filters, kobj);
615 
616 	return sysfs_emit(buf, "%d\n", filters->nr);
617 }
618 
619 static ssize_t nr_filters_store(struct kobject *kobj,
620 		struct kobj_attribute *attr, const char *buf, size_t count)
621 {
622 	struct damon_sysfs_scheme_filters *filters;
623 	int nr, err = kstrtoint(buf, 0, &nr);
624 
625 	if (err)
626 		return err;
627 	if (nr < 0)
628 		return -EINVAL;
629 
630 	filters = container_of(kobj, struct damon_sysfs_scheme_filters, kobj);
631 
632 	if (!mutex_trylock(&damon_sysfs_lock))
633 		return -EBUSY;
634 	err = damon_sysfs_scheme_filters_add_dirs(filters, nr);
635 	mutex_unlock(&damon_sysfs_lock);
636 	if (err)
637 		return err;
638 
639 	return count;
640 }
641 
642 static void damon_sysfs_scheme_filters_release(struct kobject *kobj)
643 {
644 	kfree(container_of(kobj, struct damon_sysfs_scheme_filters, kobj));
645 }
646 
647 static struct kobj_attribute damon_sysfs_scheme_filters_nr_attr =
648 		__ATTR_RW_MODE(nr_filters, 0600);
649 
650 static struct attribute *damon_sysfs_scheme_filters_attrs[] = {
651 	&damon_sysfs_scheme_filters_nr_attr.attr,
652 	NULL,
653 };
654 ATTRIBUTE_GROUPS(damon_sysfs_scheme_filters);
655 
656 static const struct kobj_type damon_sysfs_scheme_filters_ktype = {
657 	.release = damon_sysfs_scheme_filters_release,
658 	.sysfs_ops = &kobj_sysfs_ops,
659 	.default_groups = damon_sysfs_scheme_filters_groups,
660 };
661 
662 /*
663  * watermarks directory
664  */
665 
666 struct damon_sysfs_watermarks {
667 	struct kobject kobj;
668 	enum damos_wmark_metric metric;
669 	unsigned long interval_us;
670 	unsigned long high;
671 	unsigned long mid;
672 	unsigned long low;
673 };
674 
675 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
676 		enum damos_wmark_metric metric, unsigned long interval_us,
677 		unsigned long high, unsigned long mid, unsigned long low)
678 {
679 	struct damon_sysfs_watermarks *watermarks = kmalloc(
680 			sizeof(*watermarks), GFP_KERNEL);
681 
682 	if (!watermarks)
683 		return NULL;
684 	watermarks->kobj = (struct kobject){};
685 	watermarks->metric = metric;
686 	watermarks->interval_us = interval_us;
687 	watermarks->high = high;
688 	watermarks->mid = mid;
689 	watermarks->low = low;
690 	return watermarks;
691 }
692 
693 /* Should match with enum damos_wmark_metric */
694 static const char * const damon_sysfs_wmark_metric_strs[] = {
695 	"none",
696 	"free_mem_rate",
697 };
698 
699 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
700 		char *buf)
701 {
702 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
703 			struct damon_sysfs_watermarks, kobj);
704 
705 	return sysfs_emit(buf, "%s\n",
706 			damon_sysfs_wmark_metric_strs[watermarks->metric]);
707 }
708 
709 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
710 		const char *buf, size_t count)
711 {
712 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
713 			struct damon_sysfs_watermarks, kobj);
714 	enum damos_wmark_metric metric;
715 
716 	for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) {
717 		if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) {
718 			watermarks->metric = metric;
719 			return count;
720 		}
721 	}
722 	return -EINVAL;
723 }
724 
725 static ssize_t interval_us_show(struct kobject *kobj,
726 		struct kobj_attribute *attr, char *buf)
727 {
728 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
729 			struct damon_sysfs_watermarks, kobj);
730 
731 	return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
732 }
733 
734 static ssize_t interval_us_store(struct kobject *kobj,
735 		struct kobj_attribute *attr, const char *buf, size_t count)
736 {
737 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
738 			struct damon_sysfs_watermarks, kobj);
739 	int err = kstrtoul(buf, 0, &watermarks->interval_us);
740 
741 	return err ? err : count;
742 }
743 
744 static ssize_t high_show(struct kobject *kobj,
745 		struct kobj_attribute *attr, char *buf)
746 {
747 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
748 			struct damon_sysfs_watermarks, kobj);
749 
750 	return sysfs_emit(buf, "%lu\n", watermarks->high);
751 }
752 
753 static ssize_t high_store(struct kobject *kobj,
754 		struct kobj_attribute *attr, const char *buf, size_t count)
755 {
756 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
757 			struct damon_sysfs_watermarks, kobj);
758 	int err = kstrtoul(buf, 0, &watermarks->high);
759 
760 	return err ? err : count;
761 }
762 
763 static ssize_t mid_show(struct kobject *kobj,
764 		struct kobj_attribute *attr, char *buf)
765 {
766 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
767 			struct damon_sysfs_watermarks, kobj);
768 
769 	return sysfs_emit(buf, "%lu\n", watermarks->mid);
770 }
771 
772 static ssize_t mid_store(struct kobject *kobj,
773 		struct kobj_attribute *attr, const char *buf, size_t count)
774 {
775 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
776 			struct damon_sysfs_watermarks, kobj);
777 	int err = kstrtoul(buf, 0, &watermarks->mid);
778 
779 	return err ? err : count;
780 }
781 
782 static ssize_t low_show(struct kobject *kobj,
783 		struct kobj_attribute *attr, char *buf)
784 {
785 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
786 			struct damon_sysfs_watermarks, kobj);
787 
788 	return sysfs_emit(buf, "%lu\n", watermarks->low);
789 }
790 
791 static ssize_t low_store(struct kobject *kobj,
792 		struct kobj_attribute *attr, const char *buf, size_t count)
793 {
794 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
795 			struct damon_sysfs_watermarks, kobj);
796 	int err = kstrtoul(buf, 0, &watermarks->low);
797 
798 	return err ? err : count;
799 }
800 
801 static void damon_sysfs_watermarks_release(struct kobject *kobj)
802 {
803 	kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
804 }
805 
806 static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
807 		__ATTR_RW_MODE(metric, 0600);
808 
809 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
810 		__ATTR_RW_MODE(interval_us, 0600);
811 
812 static struct kobj_attribute damon_sysfs_watermarks_high_attr =
813 		__ATTR_RW_MODE(high, 0600);
814 
815 static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
816 		__ATTR_RW_MODE(mid, 0600);
817 
818 static struct kobj_attribute damon_sysfs_watermarks_low_attr =
819 		__ATTR_RW_MODE(low, 0600);
820 
821 static struct attribute *damon_sysfs_watermarks_attrs[] = {
822 	&damon_sysfs_watermarks_metric_attr.attr,
823 	&damon_sysfs_watermarks_interval_us_attr.attr,
824 	&damon_sysfs_watermarks_high_attr.attr,
825 	&damon_sysfs_watermarks_mid_attr.attr,
826 	&damon_sysfs_watermarks_low_attr.attr,
827 	NULL,
828 };
829 ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
830 
831 static const struct kobj_type damon_sysfs_watermarks_ktype = {
832 	.release = damon_sysfs_watermarks_release,
833 	.sysfs_ops = &kobj_sysfs_ops,
834 	.default_groups = damon_sysfs_watermarks_groups,
835 };
836 
837 /*
838  * quota goal directory
839  */
840 
841 struct damos_sysfs_quota_goal {
842 	struct kobject kobj;
843 	enum damos_quota_goal_metric metric;
844 	unsigned long target_value;
845 	unsigned long current_value;
846 };
847 
848 /* This should match with enum damos_action */
849 static const char * const damos_sysfs_quota_goal_metric_strs[] = {
850 	"user_input",
851 	"some_mem_psi_us",
852 };
853 
854 static struct damos_sysfs_quota_goal *damos_sysfs_quota_goal_alloc(void)
855 {
856 	return kzalloc(sizeof(struct damos_sysfs_quota_goal), GFP_KERNEL);
857 }
858 
859 static ssize_t target_metric_show(struct kobject *kobj,
860 		struct kobj_attribute *attr, char *buf)
861 {
862 	struct damos_sysfs_quota_goal *goal = container_of(kobj,
863 			struct damos_sysfs_quota_goal, kobj);
864 
865 	return sysfs_emit(buf, "%s\n",
866 			damos_sysfs_quota_goal_metric_strs[goal->metric]);
867 }
868 
869 static ssize_t target_metric_store(struct kobject *kobj,
870 		struct kobj_attribute *attr, const char *buf, size_t count)
871 {
872 	struct damos_sysfs_quota_goal *goal = container_of(kobj,
873 			struct damos_sysfs_quota_goal, kobj);
874 	enum damos_quota_goal_metric m;
875 
876 	for (m = 0; m < NR_DAMOS_QUOTA_GOAL_METRICS; m++) {
877 		if (sysfs_streq(buf, damos_sysfs_quota_goal_metric_strs[m])) {
878 			goal->metric = m;
879 			return count;
880 		}
881 	}
882 	return -EINVAL;
883 }
884 
885 static ssize_t target_value_show(struct kobject *kobj,
886 		struct kobj_attribute *attr, char *buf)
887 {
888 	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
889 			damos_sysfs_quota_goal, kobj);
890 
891 	return sysfs_emit(buf, "%lu\n", goal->target_value);
892 }
893 
894 static ssize_t target_value_store(struct kobject *kobj,
895 		struct kobj_attribute *attr, const char *buf, size_t count)
896 {
897 	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
898 			damos_sysfs_quota_goal, kobj);
899 	int err = kstrtoul(buf, 0, &goal->target_value);
900 
901 	return err ? err : count;
902 }
903 
904 static ssize_t current_value_show(struct kobject *kobj,
905 		struct kobj_attribute *attr, char *buf)
906 {
907 	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
908 			damos_sysfs_quota_goal, kobj);
909 
910 	return sysfs_emit(buf, "%lu\n", goal->current_value);
911 }
912 
913 static ssize_t current_value_store(struct kobject *kobj,
914 		struct kobj_attribute *attr, const char *buf, size_t count)
915 {
916 	struct damos_sysfs_quota_goal *goal = container_of(kobj, struct
917 			damos_sysfs_quota_goal, kobj);
918 	int err = kstrtoul(buf, 0, &goal->current_value);
919 
920 	/* feed callback should check existence of this file and read value */
921 	return err ? err : count;
922 }
923 
924 static void damos_sysfs_quota_goal_release(struct kobject *kobj)
925 {
926 	/* or, notify this release to the feed callback */
927 	kfree(container_of(kobj, struct damos_sysfs_quota_goal, kobj));
928 }
929 
930 static struct kobj_attribute damos_sysfs_quota_goal_target_metric_attr =
931 		__ATTR_RW_MODE(target_metric, 0600);
932 
933 static struct kobj_attribute damos_sysfs_quota_goal_target_value_attr =
934 		__ATTR_RW_MODE(target_value, 0600);
935 
936 static struct kobj_attribute damos_sysfs_quota_goal_current_value_attr =
937 		__ATTR_RW_MODE(current_value, 0600);
938 
939 static struct attribute *damos_sysfs_quota_goal_attrs[] = {
940 	&damos_sysfs_quota_goal_target_metric_attr.attr,
941 	&damos_sysfs_quota_goal_target_value_attr.attr,
942 	&damos_sysfs_quota_goal_current_value_attr.attr,
943 	NULL,
944 };
945 ATTRIBUTE_GROUPS(damos_sysfs_quota_goal);
946 
947 static const struct kobj_type damos_sysfs_quota_goal_ktype = {
948 	.release = damos_sysfs_quota_goal_release,
949 	.sysfs_ops = &kobj_sysfs_ops,
950 	.default_groups = damos_sysfs_quota_goal_groups,
951 };
952 
953 /*
954  * quota goals directory
955  */
956 
957 struct damos_sysfs_quota_goals {
958 	struct kobject kobj;
959 	struct damos_sysfs_quota_goal **goals_arr;	/* counted by nr */
960 	int nr;
961 };
962 
963 static struct damos_sysfs_quota_goals *damos_sysfs_quota_goals_alloc(void)
964 {
965 	return kzalloc(sizeof(struct damos_sysfs_quota_goals), GFP_KERNEL);
966 }
967 
968 static void damos_sysfs_quota_goals_rm_dirs(
969 		struct damos_sysfs_quota_goals *goals)
970 {
971 	struct damos_sysfs_quota_goal **goals_arr = goals->goals_arr;
972 	int i;
973 
974 	for (i = 0; i < goals->nr; i++)
975 		kobject_put(&goals_arr[i]->kobj);
976 	goals->nr = 0;
977 	kfree(goals_arr);
978 	goals->goals_arr = NULL;
979 }
980 
981 static int damos_sysfs_quota_goals_add_dirs(
982 		struct damos_sysfs_quota_goals *goals, int nr_goals)
983 {
984 	struct damos_sysfs_quota_goal **goals_arr, *goal;
985 	int err, i;
986 
987 	damos_sysfs_quota_goals_rm_dirs(goals);
988 	if (!nr_goals)
989 		return 0;
990 
991 	goals_arr = kmalloc_array(nr_goals, sizeof(*goals_arr),
992 			GFP_KERNEL | __GFP_NOWARN);
993 	if (!goals_arr)
994 		return -ENOMEM;
995 	goals->goals_arr = goals_arr;
996 
997 	for (i = 0; i < nr_goals; i++) {
998 		goal = damos_sysfs_quota_goal_alloc();
999 		if (!goal) {
1000 			damos_sysfs_quota_goals_rm_dirs(goals);
1001 			return -ENOMEM;
1002 		}
1003 
1004 		err = kobject_init_and_add(&goal->kobj,
1005 				&damos_sysfs_quota_goal_ktype, &goals->kobj,
1006 				"%d", i);
1007 		if (err) {
1008 			kobject_put(&goal->kobj);
1009 			damos_sysfs_quota_goals_rm_dirs(goals);
1010 			return err;
1011 		}
1012 
1013 		goals_arr[i] = goal;
1014 		goals->nr++;
1015 	}
1016 	return 0;
1017 }
1018 
1019 static ssize_t nr_goals_show(struct kobject *kobj,
1020 		struct kobj_attribute *attr, char *buf)
1021 {
1022 	struct damos_sysfs_quota_goals *goals = container_of(kobj,
1023 			struct damos_sysfs_quota_goals, kobj);
1024 
1025 	return sysfs_emit(buf, "%d\n", goals->nr);
1026 }
1027 
1028 static ssize_t nr_goals_store(struct kobject *kobj,
1029 		struct kobj_attribute *attr, const char *buf, size_t count)
1030 {
1031 	struct damos_sysfs_quota_goals *goals;
1032 	int nr, err = kstrtoint(buf, 0, &nr);
1033 
1034 	if (err)
1035 		return err;
1036 	if (nr < 0)
1037 		return -EINVAL;
1038 
1039 	goals = container_of(kobj, struct damos_sysfs_quota_goals, kobj);
1040 
1041 	if (!mutex_trylock(&damon_sysfs_lock))
1042 		return -EBUSY;
1043 	err = damos_sysfs_quota_goals_add_dirs(goals, nr);
1044 	mutex_unlock(&damon_sysfs_lock);
1045 	if (err)
1046 		return err;
1047 
1048 	return count;
1049 }
1050 
1051 static void damos_sysfs_quota_goals_release(struct kobject *kobj)
1052 {
1053 	kfree(container_of(kobj, struct damos_sysfs_quota_goals, kobj));
1054 }
1055 
1056 static struct kobj_attribute damos_sysfs_quota_goals_nr_attr =
1057 		__ATTR_RW_MODE(nr_goals, 0600);
1058 
1059 static struct attribute *damos_sysfs_quota_goals_attrs[] = {
1060 	&damos_sysfs_quota_goals_nr_attr.attr,
1061 	NULL,
1062 };
1063 ATTRIBUTE_GROUPS(damos_sysfs_quota_goals);
1064 
1065 static const struct kobj_type damos_sysfs_quota_goals_ktype = {
1066 	.release = damos_sysfs_quota_goals_release,
1067 	.sysfs_ops = &kobj_sysfs_ops,
1068 	.default_groups = damos_sysfs_quota_goals_groups,
1069 };
1070 
1071 /*
1072  * scheme/weights directory
1073  */
1074 
1075 struct damon_sysfs_weights {
1076 	struct kobject kobj;
1077 	unsigned int sz;
1078 	unsigned int nr_accesses;
1079 	unsigned int age;
1080 };
1081 
1082 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
1083 		unsigned int nr_accesses, unsigned int age)
1084 {
1085 	struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
1086 			GFP_KERNEL);
1087 
1088 	if (!weights)
1089 		return NULL;
1090 	weights->kobj = (struct kobject){};
1091 	weights->sz = sz;
1092 	weights->nr_accesses = nr_accesses;
1093 	weights->age = age;
1094 	return weights;
1095 }
1096 
1097 static ssize_t sz_permil_show(struct kobject *kobj,
1098 		struct kobj_attribute *attr, char *buf)
1099 {
1100 	struct damon_sysfs_weights *weights = container_of(kobj,
1101 			struct damon_sysfs_weights, kobj);
1102 
1103 	return sysfs_emit(buf, "%u\n", weights->sz);
1104 }
1105 
1106 static ssize_t sz_permil_store(struct kobject *kobj,
1107 		struct kobj_attribute *attr, const char *buf, size_t count)
1108 {
1109 	struct damon_sysfs_weights *weights = container_of(kobj,
1110 			struct damon_sysfs_weights, kobj);
1111 	int err = kstrtouint(buf, 0, &weights->sz);
1112 
1113 	return err ? err : count;
1114 }
1115 
1116 static ssize_t nr_accesses_permil_show(struct kobject *kobj,
1117 		struct kobj_attribute *attr, char *buf)
1118 {
1119 	struct damon_sysfs_weights *weights = container_of(kobj,
1120 			struct damon_sysfs_weights, kobj);
1121 
1122 	return sysfs_emit(buf, "%u\n", weights->nr_accesses);
1123 }
1124 
1125 static ssize_t nr_accesses_permil_store(struct kobject *kobj,
1126 		struct kobj_attribute *attr, const char *buf, size_t count)
1127 {
1128 	struct damon_sysfs_weights *weights = container_of(kobj,
1129 			struct damon_sysfs_weights, kobj);
1130 	int err = kstrtouint(buf, 0, &weights->nr_accesses);
1131 
1132 	return err ? err : count;
1133 }
1134 
1135 static ssize_t age_permil_show(struct kobject *kobj,
1136 		struct kobj_attribute *attr, char *buf)
1137 {
1138 	struct damon_sysfs_weights *weights = container_of(kobj,
1139 			struct damon_sysfs_weights, kobj);
1140 
1141 	return sysfs_emit(buf, "%u\n", weights->age);
1142 }
1143 
1144 static ssize_t age_permil_store(struct kobject *kobj,
1145 		struct kobj_attribute *attr, const char *buf, size_t count)
1146 {
1147 	struct damon_sysfs_weights *weights = container_of(kobj,
1148 			struct damon_sysfs_weights, kobj);
1149 	int err = kstrtouint(buf, 0, &weights->age);
1150 
1151 	return err ? err : count;
1152 }
1153 
1154 static void damon_sysfs_weights_release(struct kobject *kobj)
1155 {
1156 	kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
1157 }
1158 
1159 static struct kobj_attribute damon_sysfs_weights_sz_attr =
1160 		__ATTR_RW_MODE(sz_permil, 0600);
1161 
1162 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
1163 		__ATTR_RW_MODE(nr_accesses_permil, 0600);
1164 
1165 static struct kobj_attribute damon_sysfs_weights_age_attr =
1166 		__ATTR_RW_MODE(age_permil, 0600);
1167 
1168 static struct attribute *damon_sysfs_weights_attrs[] = {
1169 	&damon_sysfs_weights_sz_attr.attr,
1170 	&damon_sysfs_weights_nr_accesses_attr.attr,
1171 	&damon_sysfs_weights_age_attr.attr,
1172 	NULL,
1173 };
1174 ATTRIBUTE_GROUPS(damon_sysfs_weights);
1175 
1176 static const struct kobj_type damon_sysfs_weights_ktype = {
1177 	.release = damon_sysfs_weights_release,
1178 	.sysfs_ops = &kobj_sysfs_ops,
1179 	.default_groups = damon_sysfs_weights_groups,
1180 };
1181 
1182 /*
1183  * quotas directory
1184  */
1185 
1186 struct damon_sysfs_quotas {
1187 	struct kobject kobj;
1188 	struct damon_sysfs_weights *weights;
1189 	struct damos_sysfs_quota_goals *goals;
1190 	unsigned long ms;
1191 	unsigned long sz;
1192 	unsigned long reset_interval_ms;
1193 	unsigned long effective_sz;	/* Effective size quota in bytes */
1194 };
1195 
1196 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
1197 {
1198 	return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
1199 }
1200 
1201 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
1202 {
1203 	struct damon_sysfs_weights *weights;
1204 	struct damos_sysfs_quota_goals *goals;
1205 	int err;
1206 
1207 	weights = damon_sysfs_weights_alloc(0, 0, 0);
1208 	if (!weights)
1209 		return -ENOMEM;
1210 
1211 	err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
1212 			&quotas->kobj, "weights");
1213 	if (err) {
1214 		kobject_put(&weights->kobj);
1215 		return err;
1216 	}
1217 	quotas->weights = weights;
1218 
1219 	goals = damos_sysfs_quota_goals_alloc();
1220 	if (!goals) {
1221 		kobject_put(&weights->kobj);
1222 		return -ENOMEM;
1223 	}
1224 	err = kobject_init_and_add(&goals->kobj,
1225 			&damos_sysfs_quota_goals_ktype, &quotas->kobj,
1226 			"goals");
1227 	if (err) {
1228 		kobject_put(&weights->kobj);
1229 		kobject_put(&goals->kobj);
1230 	} else {
1231 		quotas->goals = goals;
1232 	}
1233 
1234 	return err;
1235 }
1236 
1237 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
1238 {
1239 	kobject_put(&quotas->weights->kobj);
1240 	damos_sysfs_quota_goals_rm_dirs(quotas->goals);
1241 	kobject_put(&quotas->goals->kobj);
1242 }
1243 
1244 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
1245 		char *buf)
1246 {
1247 	struct damon_sysfs_quotas *quotas = container_of(kobj,
1248 			struct damon_sysfs_quotas, kobj);
1249 
1250 	return sysfs_emit(buf, "%lu\n", quotas->ms);
1251 }
1252 
1253 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
1254 		const char *buf, size_t count)
1255 {
1256 	struct damon_sysfs_quotas *quotas = container_of(kobj,
1257 			struct damon_sysfs_quotas, kobj);
1258 	int err = kstrtoul(buf, 0, &quotas->ms);
1259 
1260 	if (err)
1261 		return -EINVAL;
1262 	return count;
1263 }
1264 
1265 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
1266 		char *buf)
1267 {
1268 	struct damon_sysfs_quotas *quotas = container_of(kobj,
1269 			struct damon_sysfs_quotas, kobj);
1270 
1271 	return sysfs_emit(buf, "%lu\n", quotas->sz);
1272 }
1273 
1274 static ssize_t bytes_store(struct kobject *kobj,
1275 		struct kobj_attribute *attr, const char *buf, size_t count)
1276 {
1277 	struct damon_sysfs_quotas *quotas = container_of(kobj,
1278 			struct damon_sysfs_quotas, kobj);
1279 	int err = kstrtoul(buf, 0, &quotas->sz);
1280 
1281 	if (err)
1282 		return -EINVAL;
1283 	return count;
1284 }
1285 
1286 static ssize_t reset_interval_ms_show(struct kobject *kobj,
1287 		struct kobj_attribute *attr, char *buf)
1288 {
1289 	struct damon_sysfs_quotas *quotas = container_of(kobj,
1290 			struct damon_sysfs_quotas, kobj);
1291 
1292 	return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
1293 }
1294 
1295 static ssize_t reset_interval_ms_store(struct kobject *kobj,
1296 		struct kobj_attribute *attr, const char *buf, size_t count)
1297 {
1298 	struct damon_sysfs_quotas *quotas = container_of(kobj,
1299 			struct damon_sysfs_quotas, kobj);
1300 	int err = kstrtoul(buf, 0, &quotas->reset_interval_ms);
1301 
1302 	if (err)
1303 		return -EINVAL;
1304 	return count;
1305 }
1306 
1307 static ssize_t effective_bytes_show(struct kobject *kobj,
1308 		struct kobj_attribute *attr, char *buf)
1309 {
1310 	struct damon_sysfs_quotas *quotas = container_of(kobj,
1311 			struct damon_sysfs_quotas, kobj);
1312 
1313 	return sysfs_emit(buf, "%lu\n", quotas->effective_sz);
1314 }
1315 
1316 static void damon_sysfs_quotas_release(struct kobject *kobj)
1317 {
1318 	kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
1319 }
1320 
1321 static struct kobj_attribute damon_sysfs_quotas_ms_attr =
1322 		__ATTR_RW_MODE(ms, 0600);
1323 
1324 static struct kobj_attribute damon_sysfs_quotas_sz_attr =
1325 		__ATTR_RW_MODE(bytes, 0600);
1326 
1327 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
1328 		__ATTR_RW_MODE(reset_interval_ms, 0600);
1329 
1330 static struct kobj_attribute damon_sysfs_quotas_effective_bytes_attr =
1331 		__ATTR_RO_MODE(effective_bytes, 0400);
1332 
1333 static struct attribute *damon_sysfs_quotas_attrs[] = {
1334 	&damon_sysfs_quotas_ms_attr.attr,
1335 	&damon_sysfs_quotas_sz_attr.attr,
1336 	&damon_sysfs_quotas_reset_interval_ms_attr.attr,
1337 	&damon_sysfs_quotas_effective_bytes_attr.attr,
1338 	NULL,
1339 };
1340 ATTRIBUTE_GROUPS(damon_sysfs_quotas);
1341 
1342 static const struct kobj_type damon_sysfs_quotas_ktype = {
1343 	.release = damon_sysfs_quotas_release,
1344 	.sysfs_ops = &kobj_sysfs_ops,
1345 	.default_groups = damon_sysfs_quotas_groups,
1346 };
1347 
1348 /*
1349  * access_pattern directory
1350  */
1351 
1352 struct damon_sysfs_access_pattern {
1353 	struct kobject kobj;
1354 	struct damon_sysfs_ul_range *sz;
1355 	struct damon_sysfs_ul_range *nr_accesses;
1356 	struct damon_sysfs_ul_range *age;
1357 };
1358 
1359 static
1360 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void)
1361 {
1362 	struct damon_sysfs_access_pattern *access_pattern =
1363 		kmalloc(sizeof(*access_pattern), GFP_KERNEL);
1364 
1365 	if (!access_pattern)
1366 		return NULL;
1367 	access_pattern->kobj = (struct kobject){};
1368 	return access_pattern;
1369 }
1370 
1371 static int damon_sysfs_access_pattern_add_range_dir(
1372 		struct damon_sysfs_access_pattern *access_pattern,
1373 		struct damon_sysfs_ul_range **range_dir_ptr,
1374 		char *name)
1375 {
1376 	struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0);
1377 	int err;
1378 
1379 	if (!range)
1380 		return -ENOMEM;
1381 	err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype,
1382 			&access_pattern->kobj, name);
1383 	if (err)
1384 		kobject_put(&range->kobj);
1385 	else
1386 		*range_dir_ptr = range;
1387 	return err;
1388 }
1389 
1390 static int damon_sysfs_access_pattern_add_dirs(
1391 		struct damon_sysfs_access_pattern *access_pattern)
1392 {
1393 	int err;
1394 
1395 	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1396 			&access_pattern->sz, "sz");
1397 	if (err)
1398 		goto put_sz_out;
1399 
1400 	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1401 			&access_pattern->nr_accesses, "nr_accesses");
1402 	if (err)
1403 		goto put_nr_accesses_sz_out;
1404 
1405 	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
1406 			&access_pattern->age, "age");
1407 	if (err)
1408 		goto put_age_nr_accesses_sz_out;
1409 	return 0;
1410 
1411 put_age_nr_accesses_sz_out:
1412 	kobject_put(&access_pattern->age->kobj);
1413 	access_pattern->age = NULL;
1414 put_nr_accesses_sz_out:
1415 	kobject_put(&access_pattern->nr_accesses->kobj);
1416 	access_pattern->nr_accesses = NULL;
1417 put_sz_out:
1418 	kobject_put(&access_pattern->sz->kobj);
1419 	access_pattern->sz = NULL;
1420 	return err;
1421 }
1422 
1423 static void damon_sysfs_access_pattern_rm_dirs(
1424 		struct damon_sysfs_access_pattern *access_pattern)
1425 {
1426 	kobject_put(&access_pattern->sz->kobj);
1427 	kobject_put(&access_pattern->nr_accesses->kobj);
1428 	kobject_put(&access_pattern->age->kobj);
1429 }
1430 
1431 static void damon_sysfs_access_pattern_release(struct kobject *kobj)
1432 {
1433 	kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj));
1434 }
1435 
1436 static struct attribute *damon_sysfs_access_pattern_attrs[] = {
1437 	NULL,
1438 };
1439 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern);
1440 
1441 static const struct kobj_type damon_sysfs_access_pattern_ktype = {
1442 	.release = damon_sysfs_access_pattern_release,
1443 	.sysfs_ops = &kobj_sysfs_ops,
1444 	.default_groups = damon_sysfs_access_pattern_groups,
1445 };
1446 
1447 /*
1448  * scheme directory
1449  */
1450 
1451 struct damon_sysfs_scheme {
1452 	struct kobject kobj;
1453 	enum damos_action action;
1454 	struct damon_sysfs_access_pattern *access_pattern;
1455 	unsigned long apply_interval_us;
1456 	struct damon_sysfs_quotas *quotas;
1457 	struct damon_sysfs_watermarks *watermarks;
1458 	struct damon_sysfs_scheme_filters *filters;
1459 	struct damon_sysfs_stats *stats;
1460 	struct damon_sysfs_scheme_regions *tried_regions;
1461 	int target_nid;
1462 };
1463 
1464 /* This should match with enum damos_action */
1465 static const char * const damon_sysfs_damos_action_strs[] = {
1466 	"willneed",
1467 	"cold",
1468 	"pageout",
1469 	"hugepage",
1470 	"nohugepage",
1471 	"lru_prio",
1472 	"lru_deprio",
1473 	"migrate_hot",
1474 	"migrate_cold",
1475 	"stat",
1476 };
1477 
1478 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
1479 		enum damos_action action, unsigned long apply_interval_us)
1480 {
1481 	struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme),
1482 				GFP_KERNEL);
1483 
1484 	if (!scheme)
1485 		return NULL;
1486 	scheme->kobj = (struct kobject){};
1487 	scheme->action = action;
1488 	scheme->apply_interval_us = apply_interval_us;
1489 	scheme->target_nid = NUMA_NO_NODE;
1490 	return scheme;
1491 }
1492 
1493 static int damon_sysfs_scheme_set_access_pattern(
1494 		struct damon_sysfs_scheme *scheme)
1495 {
1496 	struct damon_sysfs_access_pattern *access_pattern;
1497 	int err;
1498 
1499 	access_pattern = damon_sysfs_access_pattern_alloc();
1500 	if (!access_pattern)
1501 		return -ENOMEM;
1502 	err = kobject_init_and_add(&access_pattern->kobj,
1503 			&damon_sysfs_access_pattern_ktype, &scheme->kobj,
1504 			"access_pattern");
1505 	if (err)
1506 		goto out;
1507 	err = damon_sysfs_access_pattern_add_dirs(access_pattern);
1508 	if (err)
1509 		goto out;
1510 	scheme->access_pattern = access_pattern;
1511 	return 0;
1512 
1513 out:
1514 	kobject_put(&access_pattern->kobj);
1515 	return err;
1516 }
1517 
1518 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
1519 {
1520 	struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
1521 	int err;
1522 
1523 	if (!quotas)
1524 		return -ENOMEM;
1525 	err = kobject_init_and_add(&quotas->kobj, &damon_sysfs_quotas_ktype,
1526 			&scheme->kobj, "quotas");
1527 	if (err)
1528 		goto out;
1529 	err = damon_sysfs_quotas_add_dirs(quotas);
1530 	if (err)
1531 		goto out;
1532 	scheme->quotas = quotas;
1533 	return 0;
1534 
1535 out:
1536 	kobject_put(&quotas->kobj);
1537 	return err;
1538 }
1539 
1540 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
1541 {
1542 	struct damon_sysfs_watermarks *watermarks =
1543 		damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
1544 	int err;
1545 
1546 	if (!watermarks)
1547 		return -ENOMEM;
1548 	err = kobject_init_and_add(&watermarks->kobj,
1549 			&damon_sysfs_watermarks_ktype, &scheme->kobj,
1550 			"watermarks");
1551 	if (err)
1552 		kobject_put(&watermarks->kobj);
1553 	else
1554 		scheme->watermarks = watermarks;
1555 	return err;
1556 }
1557 
1558 static int damon_sysfs_scheme_set_filters(struct damon_sysfs_scheme *scheme)
1559 {
1560 	struct damon_sysfs_scheme_filters *filters =
1561 		damon_sysfs_scheme_filters_alloc();
1562 	int err;
1563 
1564 	if (!filters)
1565 		return -ENOMEM;
1566 	err = kobject_init_and_add(&filters->kobj,
1567 			&damon_sysfs_scheme_filters_ktype, &scheme->kobj,
1568 			"filters");
1569 	if (err)
1570 		kobject_put(&filters->kobj);
1571 	else
1572 		scheme->filters = filters;
1573 	return err;
1574 }
1575 
1576 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme)
1577 {
1578 	struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc();
1579 	int err;
1580 
1581 	if (!stats)
1582 		return -ENOMEM;
1583 	err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype,
1584 			&scheme->kobj, "stats");
1585 	if (err)
1586 		kobject_put(&stats->kobj);
1587 	else
1588 		scheme->stats = stats;
1589 	return err;
1590 }
1591 
1592 static int damon_sysfs_scheme_set_tried_regions(
1593 		struct damon_sysfs_scheme *scheme)
1594 {
1595 	struct damon_sysfs_scheme_regions *tried_regions =
1596 		damon_sysfs_scheme_regions_alloc();
1597 	int err;
1598 
1599 	if (!tried_regions)
1600 		return -ENOMEM;
1601 	err = kobject_init_and_add(&tried_regions->kobj,
1602 			&damon_sysfs_scheme_regions_ktype, &scheme->kobj,
1603 			"tried_regions");
1604 	if (err)
1605 		kobject_put(&tried_regions->kobj);
1606 	else
1607 		scheme->tried_regions = tried_regions;
1608 	return err;
1609 }
1610 
1611 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
1612 {
1613 	int err;
1614 
1615 	err = damon_sysfs_scheme_set_access_pattern(scheme);
1616 	if (err)
1617 		return err;
1618 	err = damon_sysfs_scheme_set_quotas(scheme);
1619 	if (err)
1620 		goto put_access_pattern_out;
1621 	err = damon_sysfs_scheme_set_watermarks(scheme);
1622 	if (err)
1623 		goto put_quotas_access_pattern_out;
1624 	err = damon_sysfs_scheme_set_filters(scheme);
1625 	if (err)
1626 		goto put_watermarks_quotas_access_pattern_out;
1627 	err = damon_sysfs_scheme_set_stats(scheme);
1628 	if (err)
1629 		goto put_filters_watermarks_quotas_access_pattern_out;
1630 	err = damon_sysfs_scheme_set_tried_regions(scheme);
1631 	if (err)
1632 		goto put_tried_regions_out;
1633 	return 0;
1634 
1635 put_tried_regions_out:
1636 	kobject_put(&scheme->tried_regions->kobj);
1637 	scheme->tried_regions = NULL;
1638 put_filters_watermarks_quotas_access_pattern_out:
1639 	kobject_put(&scheme->filters->kobj);
1640 	scheme->filters = NULL;
1641 put_watermarks_quotas_access_pattern_out:
1642 	kobject_put(&scheme->watermarks->kobj);
1643 	scheme->watermarks = NULL;
1644 put_quotas_access_pattern_out:
1645 	kobject_put(&scheme->quotas->kobj);
1646 	scheme->quotas = NULL;
1647 put_access_pattern_out:
1648 	kobject_put(&scheme->access_pattern->kobj);
1649 	scheme->access_pattern = NULL;
1650 	return err;
1651 }
1652 
1653 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
1654 {
1655 	damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
1656 	kobject_put(&scheme->access_pattern->kobj);
1657 	damon_sysfs_quotas_rm_dirs(scheme->quotas);
1658 	kobject_put(&scheme->quotas->kobj);
1659 	kobject_put(&scheme->watermarks->kobj);
1660 	damon_sysfs_scheme_filters_rm_dirs(scheme->filters);
1661 	kobject_put(&scheme->filters->kobj);
1662 	kobject_put(&scheme->stats->kobj);
1663 	damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions);
1664 	kobject_put(&scheme->tried_regions->kobj);
1665 }
1666 
1667 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
1668 		char *buf)
1669 {
1670 	struct damon_sysfs_scheme *scheme = container_of(kobj,
1671 			struct damon_sysfs_scheme, kobj);
1672 
1673 	return sysfs_emit(buf, "%s\n",
1674 			damon_sysfs_damos_action_strs[scheme->action]);
1675 }
1676 
1677 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr,
1678 		const char *buf, size_t count)
1679 {
1680 	struct damon_sysfs_scheme *scheme = container_of(kobj,
1681 			struct damon_sysfs_scheme, kobj);
1682 	enum damos_action action;
1683 
1684 	for (action = 0; action < NR_DAMOS_ACTIONS; action++) {
1685 		if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) {
1686 			scheme->action = action;
1687 			return count;
1688 		}
1689 	}
1690 	return -EINVAL;
1691 }
1692 
1693 static ssize_t apply_interval_us_show(struct kobject *kobj,
1694 		struct kobj_attribute *attr, char *buf)
1695 {
1696 	struct damon_sysfs_scheme *scheme = container_of(kobj,
1697 			struct damon_sysfs_scheme, kobj);
1698 
1699 	return sysfs_emit(buf, "%lu\n", scheme->apply_interval_us);
1700 }
1701 
1702 static ssize_t apply_interval_us_store(struct kobject *kobj,
1703 		struct kobj_attribute *attr, const char *buf, size_t count)
1704 {
1705 	struct damon_sysfs_scheme *scheme = container_of(kobj,
1706 			struct damon_sysfs_scheme, kobj);
1707 	int err = kstrtoul(buf, 0, &scheme->apply_interval_us);
1708 
1709 	return err ? err : count;
1710 }
1711 
1712 static ssize_t target_nid_show(struct kobject *kobj,
1713 		struct kobj_attribute *attr, char *buf)
1714 {
1715 	struct damon_sysfs_scheme *scheme = container_of(kobj,
1716 			struct damon_sysfs_scheme, kobj);
1717 
1718 	return sysfs_emit(buf, "%d\n", scheme->target_nid);
1719 }
1720 
1721 static ssize_t target_nid_store(struct kobject *kobj,
1722 		struct kobj_attribute *attr, const char *buf, size_t count)
1723 {
1724 	struct damon_sysfs_scheme *scheme = container_of(kobj,
1725 			struct damon_sysfs_scheme, kobj);
1726 	int err = 0;
1727 
1728 	/* TODO: error handling for target_nid range. */
1729 	err = kstrtoint(buf, 0, &scheme->target_nid);
1730 
1731 	return err ? err : count;
1732 }
1733 
1734 static void damon_sysfs_scheme_release(struct kobject *kobj)
1735 {
1736 	kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
1737 }
1738 
1739 static struct kobj_attribute damon_sysfs_scheme_action_attr =
1740 		__ATTR_RW_MODE(action, 0600);
1741 
1742 static struct kobj_attribute damon_sysfs_scheme_apply_interval_us_attr =
1743 		__ATTR_RW_MODE(apply_interval_us, 0600);
1744 
1745 static struct kobj_attribute damon_sysfs_scheme_target_nid_attr =
1746 		__ATTR_RW_MODE(target_nid, 0600);
1747 
1748 static struct attribute *damon_sysfs_scheme_attrs[] = {
1749 	&damon_sysfs_scheme_action_attr.attr,
1750 	&damon_sysfs_scheme_apply_interval_us_attr.attr,
1751 	&damon_sysfs_scheme_target_nid_attr.attr,
1752 	NULL,
1753 };
1754 ATTRIBUTE_GROUPS(damon_sysfs_scheme);
1755 
1756 static const struct kobj_type damon_sysfs_scheme_ktype = {
1757 	.release = damon_sysfs_scheme_release,
1758 	.sysfs_ops = &kobj_sysfs_ops,
1759 	.default_groups = damon_sysfs_scheme_groups,
1760 };
1761 
1762 /*
1763  * schemes directory
1764  */
1765 
1766 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void)
1767 {
1768 	return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL);
1769 }
1770 
1771 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes)
1772 {
1773 	struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr;
1774 	int i;
1775 
1776 	for (i = 0; i < schemes->nr; i++) {
1777 		damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
1778 		kobject_put(&schemes_arr[i]->kobj);
1779 	}
1780 	schemes->nr = 0;
1781 	kfree(schemes_arr);
1782 	schemes->schemes_arr = NULL;
1783 }
1784 
1785 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes,
1786 		int nr_schemes)
1787 {
1788 	struct damon_sysfs_scheme **schemes_arr, *scheme;
1789 	int err, i;
1790 
1791 	damon_sysfs_schemes_rm_dirs(schemes);
1792 	if (!nr_schemes)
1793 		return 0;
1794 
1795 	schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr),
1796 			GFP_KERNEL | __GFP_NOWARN);
1797 	if (!schemes_arr)
1798 		return -ENOMEM;
1799 	schemes->schemes_arr = schemes_arr;
1800 
1801 	for (i = 0; i < nr_schemes; i++) {
1802 		/*
1803 		 * apply_interval_us as 0 means same to aggregation interval
1804 		 * (same to before-apply_interval behavior)
1805 		 */
1806 		scheme = damon_sysfs_scheme_alloc(DAMOS_STAT, 0);
1807 		if (!scheme) {
1808 			damon_sysfs_schemes_rm_dirs(schemes);
1809 			return -ENOMEM;
1810 		}
1811 
1812 		err = kobject_init_and_add(&scheme->kobj,
1813 				&damon_sysfs_scheme_ktype, &schemes->kobj,
1814 				"%d", i);
1815 		if (err)
1816 			goto out;
1817 		err = damon_sysfs_scheme_add_dirs(scheme);
1818 		if (err)
1819 			goto out;
1820 
1821 		schemes_arr[i] = scheme;
1822 		schemes->nr++;
1823 	}
1824 	return 0;
1825 
1826 out:
1827 	damon_sysfs_schemes_rm_dirs(schemes);
1828 	kobject_put(&scheme->kobj);
1829 	return err;
1830 }
1831 
1832 static ssize_t nr_schemes_show(struct kobject *kobj,
1833 		struct kobj_attribute *attr, char *buf)
1834 {
1835 	struct damon_sysfs_schemes *schemes = container_of(kobj,
1836 			struct damon_sysfs_schemes, kobj);
1837 
1838 	return sysfs_emit(buf, "%d\n", schemes->nr);
1839 }
1840 
1841 static ssize_t nr_schemes_store(struct kobject *kobj,
1842 		struct kobj_attribute *attr, const char *buf, size_t count)
1843 {
1844 	struct damon_sysfs_schemes *schemes;
1845 	int nr, err = kstrtoint(buf, 0, &nr);
1846 
1847 	if (err)
1848 		return err;
1849 	if (nr < 0)
1850 		return -EINVAL;
1851 
1852 	schemes = container_of(kobj, struct damon_sysfs_schemes, kobj);
1853 
1854 	if (!mutex_trylock(&damon_sysfs_lock))
1855 		return -EBUSY;
1856 	err = damon_sysfs_schemes_add_dirs(schemes, nr);
1857 	mutex_unlock(&damon_sysfs_lock);
1858 	if (err)
1859 		return err;
1860 	return count;
1861 }
1862 
1863 static void damon_sysfs_schemes_release(struct kobject *kobj)
1864 {
1865 	kfree(container_of(kobj, struct damon_sysfs_schemes, kobj));
1866 }
1867 
1868 static struct kobj_attribute damon_sysfs_schemes_nr_attr =
1869 		__ATTR_RW_MODE(nr_schemes, 0600);
1870 
1871 static struct attribute *damon_sysfs_schemes_attrs[] = {
1872 	&damon_sysfs_schemes_nr_attr.attr,
1873 	NULL,
1874 };
1875 ATTRIBUTE_GROUPS(damon_sysfs_schemes);
1876 
1877 const struct kobj_type damon_sysfs_schemes_ktype = {
1878 	.release = damon_sysfs_schemes_release,
1879 	.sysfs_ops = &kobj_sysfs_ops,
1880 	.default_groups = damon_sysfs_schemes_groups,
1881 };
1882 
1883 static bool damon_sysfs_memcg_path_eq(struct mem_cgroup *memcg,
1884 		char *memcg_path_buf, char *path)
1885 {
1886 #ifdef CONFIG_MEMCG
1887 	cgroup_path(memcg->css.cgroup, memcg_path_buf, PATH_MAX);
1888 	if (sysfs_streq(memcg_path_buf, path))
1889 		return true;
1890 #endif /* CONFIG_MEMCG */
1891 	return false;
1892 }
1893 
1894 static int damon_sysfs_memcg_path_to_id(char *memcg_path, unsigned short *id)
1895 {
1896 	struct mem_cgroup *memcg;
1897 	char *path;
1898 	bool found = false;
1899 
1900 	if (!memcg_path)
1901 		return -EINVAL;
1902 
1903 	path = kmalloc(sizeof(*path) * PATH_MAX, GFP_KERNEL);
1904 	if (!path)
1905 		return -ENOMEM;
1906 
1907 	for (memcg = mem_cgroup_iter(NULL, NULL, NULL); memcg;
1908 			memcg = mem_cgroup_iter(NULL, memcg, NULL)) {
1909 		/* skip removed memcg */
1910 		if (!mem_cgroup_id(memcg))
1911 			continue;
1912 		if (damon_sysfs_memcg_path_eq(memcg, path, memcg_path)) {
1913 			*id = mem_cgroup_id(memcg);
1914 			found = true;
1915 			break;
1916 		}
1917 	}
1918 
1919 	kfree(path);
1920 	return found ? 0 : -EINVAL;
1921 }
1922 
1923 static int damon_sysfs_add_scheme_filters(struct damos *scheme,
1924 		struct damon_sysfs_scheme_filters *sysfs_filters)
1925 {
1926 	int i;
1927 
1928 	for (i = 0; i < sysfs_filters->nr; i++) {
1929 		struct damon_sysfs_scheme_filter *sysfs_filter =
1930 			sysfs_filters->filters_arr[i];
1931 		struct damos_filter *filter =
1932 			damos_new_filter(sysfs_filter->type,
1933 					sysfs_filter->matching,
1934 					sysfs_filter->allow);
1935 		int err;
1936 
1937 		if (!filter)
1938 			return -ENOMEM;
1939 		if (filter->type == DAMOS_FILTER_TYPE_MEMCG) {
1940 			err = damon_sysfs_memcg_path_to_id(
1941 					sysfs_filter->memcg_path,
1942 					&filter->memcg_id);
1943 			if (err) {
1944 				damos_destroy_filter(filter);
1945 				return err;
1946 			}
1947 		} else if (filter->type == DAMOS_FILTER_TYPE_ADDR) {
1948 			if (sysfs_filter->addr_range.end <
1949 					sysfs_filter->addr_range.start) {
1950 				damos_destroy_filter(filter);
1951 				return -EINVAL;
1952 			}
1953 			filter->addr_range = sysfs_filter->addr_range;
1954 		} else if (filter->type == DAMOS_FILTER_TYPE_TARGET) {
1955 			filter->target_idx = sysfs_filter->target_idx;
1956 		}
1957 
1958 		damos_add_filter(scheme, filter);
1959 	}
1960 	return 0;
1961 }
1962 
1963 static int damos_sysfs_add_quota_score(
1964 		struct damos_sysfs_quota_goals *sysfs_goals,
1965 		struct damos_quota *quota)
1966 {
1967 	struct damos_quota_goal *goal;
1968 	int i;
1969 
1970 	for (i = 0; i < sysfs_goals->nr; i++) {
1971 		struct damos_sysfs_quota_goal *sysfs_goal =
1972 			sysfs_goals->goals_arr[i];
1973 
1974 		if (!sysfs_goal->target_value)
1975 			continue;
1976 
1977 		goal = damos_new_quota_goal(sysfs_goal->metric,
1978 				sysfs_goal->target_value);
1979 		if (!goal)
1980 			return -ENOMEM;
1981 		if (sysfs_goal->metric == DAMOS_QUOTA_USER_INPUT)
1982 			goal->current_value = sysfs_goal->current_value;
1983 		damos_add_quota_goal(quota, goal);
1984 	}
1985 	return 0;
1986 }
1987 
1988 int damos_sysfs_set_quota_scores(struct damon_sysfs_schemes *sysfs_schemes,
1989 		struct damon_ctx *ctx)
1990 {
1991 	struct damos *scheme;
1992 	struct damos_quota quota = {};
1993 	int i = 0;
1994 
1995 	INIT_LIST_HEAD(&quota.goals);
1996 	damon_for_each_scheme(scheme, ctx) {
1997 		struct damon_sysfs_scheme *sysfs_scheme;
1998 		struct damos_quota_goal *g, *g_next;
1999 		int err;
2000 
2001 		/* user could have removed the scheme sysfs dir */
2002 		if (i >= sysfs_schemes->nr)
2003 			break;
2004 
2005 		sysfs_scheme = sysfs_schemes->schemes_arr[i];
2006 		err = damos_sysfs_add_quota_score(sysfs_scheme->quotas->goals,
2007 				&quota);
2008 		if (err) {
2009 			damos_for_each_quota_goal_safe(g, g_next, &quota)
2010 				damos_destroy_quota_goal(g);
2011 			return err;
2012 		}
2013 		err = damos_commit_quota_goals(&scheme->quota, &quota);
2014 		damos_for_each_quota_goal_safe(g, g_next, &quota)
2015 			damos_destroy_quota_goal(g);
2016 		if (err)
2017 			return err;
2018 		i++;
2019 	}
2020 	return 0;
2021 }
2022 
2023 void damos_sysfs_update_effective_quotas(
2024 		struct damon_sysfs_schemes *sysfs_schemes,
2025 		struct damon_ctx *ctx)
2026 {
2027 	struct damos *scheme;
2028 	int schemes_idx = 0;
2029 
2030 	damon_for_each_scheme(scheme, ctx) {
2031 		struct damon_sysfs_quotas *sysfs_quotas;
2032 
2033 		/* user could have removed the scheme sysfs dir */
2034 		if (schemes_idx >= sysfs_schemes->nr)
2035 			break;
2036 
2037 		sysfs_quotas =
2038 			sysfs_schemes->schemes_arr[schemes_idx++]->quotas;
2039 		sysfs_quotas->effective_sz = scheme->quota.esz;
2040 	}
2041 }
2042 
2043 static struct damos *damon_sysfs_mk_scheme(
2044 		struct damon_sysfs_scheme *sysfs_scheme)
2045 {
2046 	struct damon_sysfs_access_pattern *access_pattern =
2047 		sysfs_scheme->access_pattern;
2048 	struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
2049 	struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
2050 	struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
2051 	struct damon_sysfs_scheme_filters *sysfs_filters =
2052 		sysfs_scheme->filters;
2053 	struct damos *scheme;
2054 	int err;
2055 
2056 	struct damos_access_pattern pattern = {
2057 		.min_sz_region = access_pattern->sz->min,
2058 		.max_sz_region = access_pattern->sz->max,
2059 		.min_nr_accesses = access_pattern->nr_accesses->min,
2060 		.max_nr_accesses = access_pattern->nr_accesses->max,
2061 		.min_age_region = access_pattern->age->min,
2062 		.max_age_region = access_pattern->age->max,
2063 	};
2064 	struct damos_quota quota = {
2065 		.ms = sysfs_quotas->ms,
2066 		.sz = sysfs_quotas->sz,
2067 		.reset_interval = sysfs_quotas->reset_interval_ms,
2068 		.weight_sz = sysfs_weights->sz,
2069 		.weight_nr_accesses = sysfs_weights->nr_accesses,
2070 		.weight_age = sysfs_weights->age,
2071 	};
2072 	struct damos_watermarks wmarks = {
2073 		.metric = sysfs_wmarks->metric,
2074 		.interval = sysfs_wmarks->interval_us,
2075 		.high = sysfs_wmarks->high,
2076 		.mid = sysfs_wmarks->mid,
2077 		.low = sysfs_wmarks->low,
2078 	};
2079 
2080 	scheme = damon_new_scheme(&pattern, sysfs_scheme->action,
2081 			sysfs_scheme->apply_interval_us, &quota, &wmarks,
2082 			sysfs_scheme->target_nid);
2083 	if (!scheme)
2084 		return NULL;
2085 
2086 	err = damos_sysfs_add_quota_score(sysfs_quotas->goals, &scheme->quota);
2087 	if (err) {
2088 		damon_destroy_scheme(scheme);
2089 		return NULL;
2090 	}
2091 
2092 	err = damon_sysfs_add_scheme_filters(scheme, sysfs_filters);
2093 	if (err) {
2094 		damon_destroy_scheme(scheme);
2095 		return NULL;
2096 	}
2097 	return scheme;
2098 }
2099 
2100 int damon_sysfs_add_schemes(struct damon_ctx *ctx,
2101 		struct damon_sysfs_schemes *sysfs_schemes)
2102 {
2103 	int i;
2104 
2105 	for (i = 0; i < sysfs_schemes->nr; i++) {
2106 		struct damos *scheme, *next;
2107 
2108 		scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]);
2109 		if (!scheme) {
2110 			damon_for_each_scheme_safe(scheme, next, ctx)
2111 				damon_destroy_scheme(scheme);
2112 			return -ENOMEM;
2113 		}
2114 		damon_add_scheme(ctx, scheme);
2115 	}
2116 	return 0;
2117 }
2118 
2119 void damon_sysfs_schemes_update_stats(
2120 		struct damon_sysfs_schemes *sysfs_schemes,
2121 		struct damon_ctx *ctx)
2122 {
2123 	struct damos *scheme;
2124 	int schemes_idx = 0;
2125 
2126 	damon_for_each_scheme(scheme, ctx) {
2127 		struct damon_sysfs_stats *sysfs_stats;
2128 
2129 		/* user could have removed the scheme sysfs dir */
2130 		if (schemes_idx >= sysfs_schemes->nr)
2131 			break;
2132 
2133 		sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats;
2134 		sysfs_stats->nr_tried = scheme->stat.nr_tried;
2135 		sysfs_stats->sz_tried = scheme->stat.sz_tried;
2136 		sysfs_stats->nr_applied = scheme->stat.nr_applied;
2137 		sysfs_stats->sz_applied = scheme->stat.sz_applied;
2138 		sysfs_stats->sz_ops_filter_passed =
2139 			scheme->stat.sz_ops_filter_passed;
2140 		sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds;
2141 	}
2142 }
2143 
2144 /**
2145  * damos_sysfs_populate_region_dir() - Populate a schemes tried region dir.
2146  * @sysfs_schemes:	Schemes directory to populate regions directory.
2147  * @ctx:		Corresponding DAMON context.
2148  * @t:			DAMON target of @r.
2149  * @r:			DAMON region to populate the directory for.
2150  * @s:			Corresponding scheme.
2151  * @total_bytes_only:	Whether the request is for bytes update only.
2152  * @sz_filter_passed:	Bytes of @r that passed filters of @s.
2153  *
2154  * Called from DAMOS walk callback while holding damon_sysfs_lock.
2155  */
2156 void damos_sysfs_populate_region_dir(struct damon_sysfs_schemes *sysfs_schemes,
2157 		struct damon_ctx *ctx, struct damon_target *t,
2158 		struct damon_region *r, struct damos *s, bool total_bytes_only,
2159 		unsigned long sz_filter_passed)
2160 {
2161 	struct damos *scheme;
2162 	struct damon_sysfs_scheme_regions *sysfs_regions;
2163 	struct damon_sysfs_scheme_region *region;
2164 	int schemes_idx = 0;
2165 
2166 	damon_for_each_scheme(scheme, ctx) {
2167 		if (scheme == s)
2168 			break;
2169 		schemes_idx++;
2170 	}
2171 
2172 	/* user could have removed the scheme sysfs dir */
2173 	if (schemes_idx >= sysfs_schemes->nr)
2174 		return;
2175 
2176 	sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions;
2177 	sysfs_regions->total_bytes += r->ar.end - r->ar.start;
2178 	if (total_bytes_only)
2179 		return;
2180 
2181 	region = damon_sysfs_scheme_region_alloc(r);
2182 	if (!region)
2183 		return;
2184 	region->sz_filter_passed = sz_filter_passed;
2185 	list_add_tail(&region->list, &sysfs_regions->regions_list);
2186 	sysfs_regions->nr_regions++;
2187 	if (kobject_init_and_add(&region->kobj,
2188 				&damon_sysfs_scheme_region_ktype,
2189 				&sysfs_regions->kobj, "%d",
2190 				sysfs_regions->nr_regions++)) {
2191 		kobject_put(&region->kobj);
2192 	}
2193 }
2194 
2195 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
2196 int damon_sysfs_schemes_clear_regions(
2197 		struct damon_sysfs_schemes *sysfs_schemes)
2198 {
2199 	int i;
2200 
2201 	for (i = 0; i < sysfs_schemes->nr; i++) {
2202 		struct damon_sysfs_scheme *sysfs_scheme;
2203 
2204 		sysfs_scheme = sysfs_schemes->schemes_arr[i];
2205 		damon_sysfs_scheme_regions_rm_dirs(
2206 				sysfs_scheme->tried_regions);
2207 		sysfs_scheme->tried_regions->total_bytes = 0;
2208 	}
2209 	return 0;
2210 }
2211