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