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