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