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