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