xref: /openbmc/linux/mm/damon/sysfs-schemes.c (revision 27e45f2e)
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 
10 #include "sysfs-common.h"
11 
12 /*
13  * scheme region directory
14  */
15 
16 struct damon_sysfs_scheme_region {
17 	struct kobject kobj;
18 	struct damon_addr_range ar;
19 	unsigned int nr_accesses;
20 	unsigned int age;
21 	struct list_head list;
22 };
23 
24 static struct damon_sysfs_scheme_region *damon_sysfs_scheme_region_alloc(
25 		struct damon_region *region)
26 {
27 	struct damon_sysfs_scheme_region *sysfs_region = kmalloc(
28 			sizeof(*sysfs_region), GFP_KERNEL);
29 
30 	if (!sysfs_region)
31 		return NULL;
32 	sysfs_region->kobj = (struct kobject){};
33 	sysfs_region->ar = region->ar;
34 	sysfs_region->nr_accesses = region->nr_accesses;
35 	sysfs_region->age = region->age;
36 	INIT_LIST_HEAD(&sysfs_region->list);
37 	return sysfs_region;
38 }
39 
40 static ssize_t start_show(struct kobject *kobj, struct kobj_attribute *attr,
41 		char *buf)
42 {
43 	struct damon_sysfs_scheme_region *region = container_of(kobj,
44 			struct damon_sysfs_scheme_region, kobj);
45 
46 	return sysfs_emit(buf, "%lu\n", region->ar.start);
47 }
48 
49 static ssize_t end_show(struct kobject *kobj, struct kobj_attribute *attr,
50 		char *buf)
51 {
52 	struct damon_sysfs_scheme_region *region = container_of(kobj,
53 			struct damon_sysfs_scheme_region, kobj);
54 
55 	return sysfs_emit(buf, "%lu\n", region->ar.end);
56 }
57 
58 static ssize_t nr_accesses_show(struct kobject *kobj,
59 		struct kobj_attribute *attr, char *buf)
60 {
61 	struct damon_sysfs_scheme_region *region = container_of(kobj,
62 			struct damon_sysfs_scheme_region, kobj);
63 
64 	return sysfs_emit(buf, "%u\n", region->nr_accesses);
65 }
66 
67 static ssize_t age_show(struct kobject *kobj, struct kobj_attribute *attr,
68 		char *buf)
69 {
70 	struct damon_sysfs_scheme_region *region = container_of(kobj,
71 			struct damon_sysfs_scheme_region, kobj);
72 
73 	return sysfs_emit(buf, "%u\n", region->age);
74 }
75 
76 static void damon_sysfs_scheme_region_release(struct kobject *kobj)
77 {
78 	struct damon_sysfs_scheme_region *region = container_of(kobj,
79 			struct damon_sysfs_scheme_region, kobj);
80 
81 	list_del(&region->list);
82 	kfree(region);
83 }
84 
85 static struct kobj_attribute damon_sysfs_scheme_region_start_attr =
86 		__ATTR_RO_MODE(start, 0400);
87 
88 static struct kobj_attribute damon_sysfs_scheme_region_end_attr =
89 		__ATTR_RO_MODE(end, 0400);
90 
91 static struct kobj_attribute damon_sysfs_scheme_region_nr_accesses_attr =
92 		__ATTR_RO_MODE(nr_accesses, 0400);
93 
94 static struct kobj_attribute damon_sysfs_scheme_region_age_attr =
95 		__ATTR_RO_MODE(age, 0400);
96 
97 static struct attribute *damon_sysfs_scheme_region_attrs[] = {
98 	&damon_sysfs_scheme_region_start_attr.attr,
99 	&damon_sysfs_scheme_region_end_attr.attr,
100 	&damon_sysfs_scheme_region_nr_accesses_attr.attr,
101 	&damon_sysfs_scheme_region_age_attr.attr,
102 	NULL,
103 };
104 ATTRIBUTE_GROUPS(damon_sysfs_scheme_region);
105 
106 static struct kobj_type damon_sysfs_scheme_region_ktype = {
107 	.release = damon_sysfs_scheme_region_release,
108 	.sysfs_ops = &kobj_sysfs_ops,
109 	.default_groups = damon_sysfs_scheme_region_groups,
110 };
111 
112 /*
113  * scheme regions directory
114  */
115 
116 struct damon_sysfs_scheme_regions {
117 	struct kobject kobj;
118 	struct list_head regions_list;
119 	int nr_regions;
120 };
121 
122 static struct damon_sysfs_scheme_regions *
123 damon_sysfs_scheme_regions_alloc(void)
124 {
125 	struct damon_sysfs_scheme_regions *regions = kmalloc(sizeof(*regions),
126 			GFP_KERNEL);
127 
128 	regions->kobj = (struct kobject){};
129 	INIT_LIST_HEAD(&regions->regions_list);
130 	regions->nr_regions = 0;
131 	return regions;
132 }
133 
134 static void damon_sysfs_scheme_regions_rm_dirs(
135 		struct damon_sysfs_scheme_regions *regions)
136 {
137 	struct damon_sysfs_scheme_region *r, *next;
138 
139 	list_for_each_entry_safe(r, next, &regions->regions_list, list) {
140 		/* release function deletes it from the list */
141 		kobject_put(&r->kobj);
142 		regions->nr_regions--;
143 	}
144 }
145 
146 static void damon_sysfs_scheme_regions_release(struct kobject *kobj)
147 {
148 	kfree(container_of(kobj, struct damon_sysfs_scheme_regions, kobj));
149 }
150 
151 static struct attribute *damon_sysfs_scheme_regions_attrs[] = {
152 	NULL,
153 };
154 ATTRIBUTE_GROUPS(damon_sysfs_scheme_regions);
155 
156 static struct kobj_type damon_sysfs_scheme_regions_ktype = {
157 	.release = damon_sysfs_scheme_regions_release,
158 	.sysfs_ops = &kobj_sysfs_ops,
159 	.default_groups = damon_sysfs_scheme_regions_groups,
160 };
161 
162 /*
163  * schemes/stats directory
164  */
165 
166 struct damon_sysfs_stats {
167 	struct kobject kobj;
168 	unsigned long nr_tried;
169 	unsigned long sz_tried;
170 	unsigned long nr_applied;
171 	unsigned long sz_applied;
172 	unsigned long qt_exceeds;
173 };
174 
175 static struct damon_sysfs_stats *damon_sysfs_stats_alloc(void)
176 {
177 	return kzalloc(sizeof(struct damon_sysfs_stats), GFP_KERNEL);
178 }
179 
180 static ssize_t nr_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
181 		char *buf)
182 {
183 	struct damon_sysfs_stats *stats = container_of(kobj,
184 			struct damon_sysfs_stats, kobj);
185 
186 	return sysfs_emit(buf, "%lu\n", stats->nr_tried);
187 }
188 
189 static ssize_t sz_tried_show(struct kobject *kobj, struct kobj_attribute *attr,
190 		char *buf)
191 {
192 	struct damon_sysfs_stats *stats = container_of(kobj,
193 			struct damon_sysfs_stats, kobj);
194 
195 	return sysfs_emit(buf, "%lu\n", stats->sz_tried);
196 }
197 
198 static ssize_t nr_applied_show(struct kobject *kobj,
199 		struct kobj_attribute *attr, char *buf)
200 {
201 	struct damon_sysfs_stats *stats = container_of(kobj,
202 			struct damon_sysfs_stats, kobj);
203 
204 	return sysfs_emit(buf, "%lu\n", stats->nr_applied);
205 }
206 
207 static ssize_t sz_applied_show(struct kobject *kobj,
208 		struct kobj_attribute *attr, char *buf)
209 {
210 	struct damon_sysfs_stats *stats = container_of(kobj,
211 			struct damon_sysfs_stats, kobj);
212 
213 	return sysfs_emit(buf, "%lu\n", stats->sz_applied);
214 }
215 
216 static ssize_t qt_exceeds_show(struct kobject *kobj,
217 		struct kobj_attribute *attr, char *buf)
218 {
219 	struct damon_sysfs_stats *stats = container_of(kobj,
220 			struct damon_sysfs_stats, kobj);
221 
222 	return sysfs_emit(buf, "%lu\n", stats->qt_exceeds);
223 }
224 
225 static void damon_sysfs_stats_release(struct kobject *kobj)
226 {
227 	kfree(container_of(kobj, struct damon_sysfs_stats, kobj));
228 }
229 
230 static struct kobj_attribute damon_sysfs_stats_nr_tried_attr =
231 		__ATTR_RO_MODE(nr_tried, 0400);
232 
233 static struct kobj_attribute damon_sysfs_stats_sz_tried_attr =
234 		__ATTR_RO_MODE(sz_tried, 0400);
235 
236 static struct kobj_attribute damon_sysfs_stats_nr_applied_attr =
237 		__ATTR_RO_MODE(nr_applied, 0400);
238 
239 static struct kobj_attribute damon_sysfs_stats_sz_applied_attr =
240 		__ATTR_RO_MODE(sz_applied, 0400);
241 
242 static struct kobj_attribute damon_sysfs_stats_qt_exceeds_attr =
243 		__ATTR_RO_MODE(qt_exceeds, 0400);
244 
245 static struct attribute *damon_sysfs_stats_attrs[] = {
246 	&damon_sysfs_stats_nr_tried_attr.attr,
247 	&damon_sysfs_stats_sz_tried_attr.attr,
248 	&damon_sysfs_stats_nr_applied_attr.attr,
249 	&damon_sysfs_stats_sz_applied_attr.attr,
250 	&damon_sysfs_stats_qt_exceeds_attr.attr,
251 	NULL,
252 };
253 ATTRIBUTE_GROUPS(damon_sysfs_stats);
254 
255 static struct kobj_type damon_sysfs_stats_ktype = {
256 	.release = damon_sysfs_stats_release,
257 	.sysfs_ops = &kobj_sysfs_ops,
258 	.default_groups = damon_sysfs_stats_groups,
259 };
260 
261 /*
262  * watermarks directory
263  */
264 
265 struct damon_sysfs_watermarks {
266 	struct kobject kobj;
267 	enum damos_wmark_metric metric;
268 	unsigned long interval_us;
269 	unsigned long high;
270 	unsigned long mid;
271 	unsigned long low;
272 };
273 
274 static struct damon_sysfs_watermarks *damon_sysfs_watermarks_alloc(
275 		enum damos_wmark_metric metric, unsigned long interval_us,
276 		unsigned long high, unsigned long mid, unsigned long low)
277 {
278 	struct damon_sysfs_watermarks *watermarks = kmalloc(
279 			sizeof(*watermarks), GFP_KERNEL);
280 
281 	if (!watermarks)
282 		return NULL;
283 	watermarks->kobj = (struct kobject){};
284 	watermarks->metric = metric;
285 	watermarks->interval_us = interval_us;
286 	watermarks->high = high;
287 	watermarks->mid = mid;
288 	watermarks->low = low;
289 	return watermarks;
290 }
291 
292 /* Should match with enum damos_wmark_metric */
293 static const char * const damon_sysfs_wmark_metric_strs[] = {
294 	"none",
295 	"free_mem_rate",
296 };
297 
298 static ssize_t metric_show(struct kobject *kobj, struct kobj_attribute *attr,
299 		char *buf)
300 {
301 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
302 			struct damon_sysfs_watermarks, kobj);
303 
304 	return sysfs_emit(buf, "%s\n",
305 			damon_sysfs_wmark_metric_strs[watermarks->metric]);
306 }
307 
308 static ssize_t metric_store(struct kobject *kobj, struct kobj_attribute *attr,
309 		const char *buf, size_t count)
310 {
311 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
312 			struct damon_sysfs_watermarks, kobj);
313 	enum damos_wmark_metric metric;
314 
315 	for (metric = 0; metric < NR_DAMOS_WMARK_METRICS; metric++) {
316 		if (sysfs_streq(buf, damon_sysfs_wmark_metric_strs[metric])) {
317 			watermarks->metric = metric;
318 			return count;
319 		}
320 	}
321 	return -EINVAL;
322 }
323 
324 static ssize_t interval_us_show(struct kobject *kobj,
325 		struct kobj_attribute *attr, char *buf)
326 {
327 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
328 			struct damon_sysfs_watermarks, kobj);
329 
330 	return sysfs_emit(buf, "%lu\n", watermarks->interval_us);
331 }
332 
333 static ssize_t interval_us_store(struct kobject *kobj,
334 		struct kobj_attribute *attr, const char *buf, size_t count)
335 {
336 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
337 			struct damon_sysfs_watermarks, kobj);
338 	int err = kstrtoul(buf, 0, &watermarks->interval_us);
339 
340 	return err ? err : count;
341 }
342 
343 static ssize_t high_show(struct kobject *kobj,
344 		struct kobj_attribute *attr, char *buf)
345 {
346 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
347 			struct damon_sysfs_watermarks, kobj);
348 
349 	return sysfs_emit(buf, "%lu\n", watermarks->high);
350 }
351 
352 static ssize_t high_store(struct kobject *kobj,
353 		struct kobj_attribute *attr, const char *buf, size_t count)
354 {
355 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
356 			struct damon_sysfs_watermarks, kobj);
357 	int err = kstrtoul(buf, 0, &watermarks->high);
358 
359 	return err ? err : count;
360 }
361 
362 static ssize_t mid_show(struct kobject *kobj,
363 		struct kobj_attribute *attr, char *buf)
364 {
365 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
366 			struct damon_sysfs_watermarks, kobj);
367 
368 	return sysfs_emit(buf, "%lu\n", watermarks->mid);
369 }
370 
371 static ssize_t mid_store(struct kobject *kobj,
372 		struct kobj_attribute *attr, const char *buf, size_t count)
373 {
374 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
375 			struct damon_sysfs_watermarks, kobj);
376 	int err = kstrtoul(buf, 0, &watermarks->mid);
377 
378 	return err ? err : count;
379 }
380 
381 static ssize_t low_show(struct kobject *kobj,
382 		struct kobj_attribute *attr, char *buf)
383 {
384 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
385 			struct damon_sysfs_watermarks, kobj);
386 
387 	return sysfs_emit(buf, "%lu\n", watermarks->low);
388 }
389 
390 static ssize_t low_store(struct kobject *kobj,
391 		struct kobj_attribute *attr, const char *buf, size_t count)
392 {
393 	struct damon_sysfs_watermarks *watermarks = container_of(kobj,
394 			struct damon_sysfs_watermarks, kobj);
395 	int err = kstrtoul(buf, 0, &watermarks->low);
396 
397 	return err ? err : count;
398 }
399 
400 static void damon_sysfs_watermarks_release(struct kobject *kobj)
401 {
402 	kfree(container_of(kobj, struct damon_sysfs_watermarks, kobj));
403 }
404 
405 static struct kobj_attribute damon_sysfs_watermarks_metric_attr =
406 		__ATTR_RW_MODE(metric, 0600);
407 
408 static struct kobj_attribute damon_sysfs_watermarks_interval_us_attr =
409 		__ATTR_RW_MODE(interval_us, 0600);
410 
411 static struct kobj_attribute damon_sysfs_watermarks_high_attr =
412 		__ATTR_RW_MODE(high, 0600);
413 
414 static struct kobj_attribute damon_sysfs_watermarks_mid_attr =
415 		__ATTR_RW_MODE(mid, 0600);
416 
417 static struct kobj_attribute damon_sysfs_watermarks_low_attr =
418 		__ATTR_RW_MODE(low, 0600);
419 
420 static struct attribute *damon_sysfs_watermarks_attrs[] = {
421 	&damon_sysfs_watermarks_metric_attr.attr,
422 	&damon_sysfs_watermarks_interval_us_attr.attr,
423 	&damon_sysfs_watermarks_high_attr.attr,
424 	&damon_sysfs_watermarks_mid_attr.attr,
425 	&damon_sysfs_watermarks_low_attr.attr,
426 	NULL,
427 };
428 ATTRIBUTE_GROUPS(damon_sysfs_watermarks);
429 
430 static struct kobj_type damon_sysfs_watermarks_ktype = {
431 	.release = damon_sysfs_watermarks_release,
432 	.sysfs_ops = &kobj_sysfs_ops,
433 	.default_groups = damon_sysfs_watermarks_groups,
434 };
435 
436 /*
437  * scheme/weights directory
438  */
439 
440 struct damon_sysfs_weights {
441 	struct kobject kobj;
442 	unsigned int sz;
443 	unsigned int nr_accesses;
444 	unsigned int age;
445 };
446 
447 static struct damon_sysfs_weights *damon_sysfs_weights_alloc(unsigned int sz,
448 		unsigned int nr_accesses, unsigned int age)
449 {
450 	struct damon_sysfs_weights *weights = kmalloc(sizeof(*weights),
451 			GFP_KERNEL);
452 
453 	if (!weights)
454 		return NULL;
455 	weights->kobj = (struct kobject){};
456 	weights->sz = sz;
457 	weights->nr_accesses = nr_accesses;
458 	weights->age = age;
459 	return weights;
460 }
461 
462 static ssize_t sz_permil_show(struct kobject *kobj,
463 		struct kobj_attribute *attr, char *buf)
464 {
465 	struct damon_sysfs_weights *weights = container_of(kobj,
466 			struct damon_sysfs_weights, kobj);
467 
468 	return sysfs_emit(buf, "%u\n", weights->sz);
469 }
470 
471 static ssize_t sz_permil_store(struct kobject *kobj,
472 		struct kobj_attribute *attr, const char *buf, size_t count)
473 {
474 	struct damon_sysfs_weights *weights = container_of(kobj,
475 			struct damon_sysfs_weights, kobj);
476 	int err = kstrtouint(buf, 0, &weights->sz);
477 
478 	return err ? err : count;
479 }
480 
481 static ssize_t nr_accesses_permil_show(struct kobject *kobj,
482 		struct kobj_attribute *attr, char *buf)
483 {
484 	struct damon_sysfs_weights *weights = container_of(kobj,
485 			struct damon_sysfs_weights, kobj);
486 
487 	return sysfs_emit(buf, "%u\n", weights->nr_accesses);
488 }
489 
490 static ssize_t nr_accesses_permil_store(struct kobject *kobj,
491 		struct kobj_attribute *attr, const char *buf, size_t count)
492 {
493 	struct damon_sysfs_weights *weights = container_of(kobj,
494 			struct damon_sysfs_weights, kobj);
495 	int err = kstrtouint(buf, 0, &weights->nr_accesses);
496 
497 	return err ? err : count;
498 }
499 
500 static ssize_t age_permil_show(struct kobject *kobj,
501 		struct kobj_attribute *attr, char *buf)
502 {
503 	struct damon_sysfs_weights *weights = container_of(kobj,
504 			struct damon_sysfs_weights, kobj);
505 
506 	return sysfs_emit(buf, "%u\n", weights->age);
507 }
508 
509 static ssize_t age_permil_store(struct kobject *kobj,
510 		struct kobj_attribute *attr, const char *buf, size_t count)
511 {
512 	struct damon_sysfs_weights *weights = container_of(kobj,
513 			struct damon_sysfs_weights, kobj);
514 	int err = kstrtouint(buf, 0, &weights->age);
515 
516 	return err ? err : count;
517 }
518 
519 static void damon_sysfs_weights_release(struct kobject *kobj)
520 {
521 	kfree(container_of(kobj, struct damon_sysfs_weights, kobj));
522 }
523 
524 static struct kobj_attribute damon_sysfs_weights_sz_attr =
525 		__ATTR_RW_MODE(sz_permil, 0600);
526 
527 static struct kobj_attribute damon_sysfs_weights_nr_accesses_attr =
528 		__ATTR_RW_MODE(nr_accesses_permil, 0600);
529 
530 static struct kobj_attribute damon_sysfs_weights_age_attr =
531 		__ATTR_RW_MODE(age_permil, 0600);
532 
533 static struct attribute *damon_sysfs_weights_attrs[] = {
534 	&damon_sysfs_weights_sz_attr.attr,
535 	&damon_sysfs_weights_nr_accesses_attr.attr,
536 	&damon_sysfs_weights_age_attr.attr,
537 	NULL,
538 };
539 ATTRIBUTE_GROUPS(damon_sysfs_weights);
540 
541 static struct kobj_type damon_sysfs_weights_ktype = {
542 	.release = damon_sysfs_weights_release,
543 	.sysfs_ops = &kobj_sysfs_ops,
544 	.default_groups = damon_sysfs_weights_groups,
545 };
546 
547 /*
548  * quotas directory
549  */
550 
551 struct damon_sysfs_quotas {
552 	struct kobject kobj;
553 	struct damon_sysfs_weights *weights;
554 	unsigned long ms;
555 	unsigned long sz;
556 	unsigned long reset_interval_ms;
557 };
558 
559 static struct damon_sysfs_quotas *damon_sysfs_quotas_alloc(void)
560 {
561 	return kzalloc(sizeof(struct damon_sysfs_quotas), GFP_KERNEL);
562 }
563 
564 static int damon_sysfs_quotas_add_dirs(struct damon_sysfs_quotas *quotas)
565 {
566 	struct damon_sysfs_weights *weights;
567 	int err;
568 
569 	weights = damon_sysfs_weights_alloc(0, 0, 0);
570 	if (!weights)
571 		return -ENOMEM;
572 
573 	err = kobject_init_and_add(&weights->kobj, &damon_sysfs_weights_ktype,
574 			&quotas->kobj, "weights");
575 	if (err)
576 		kobject_put(&weights->kobj);
577 	else
578 		quotas->weights = weights;
579 	return err;
580 }
581 
582 static void damon_sysfs_quotas_rm_dirs(struct damon_sysfs_quotas *quotas)
583 {
584 	kobject_put(&quotas->weights->kobj);
585 }
586 
587 static ssize_t ms_show(struct kobject *kobj, struct kobj_attribute *attr,
588 		char *buf)
589 {
590 	struct damon_sysfs_quotas *quotas = container_of(kobj,
591 			struct damon_sysfs_quotas, kobj);
592 
593 	return sysfs_emit(buf, "%lu\n", quotas->ms);
594 }
595 
596 static ssize_t ms_store(struct kobject *kobj, struct kobj_attribute *attr,
597 		const char *buf, size_t count)
598 {
599 	struct damon_sysfs_quotas *quotas = container_of(kobj,
600 			struct damon_sysfs_quotas, kobj);
601 	int err = kstrtoul(buf, 0, &quotas->ms);
602 
603 	if (err)
604 		return -EINVAL;
605 	return count;
606 }
607 
608 static ssize_t bytes_show(struct kobject *kobj, struct kobj_attribute *attr,
609 		char *buf)
610 {
611 	struct damon_sysfs_quotas *quotas = container_of(kobj,
612 			struct damon_sysfs_quotas, kobj);
613 
614 	return sysfs_emit(buf, "%lu\n", quotas->sz);
615 }
616 
617 static ssize_t bytes_store(struct kobject *kobj,
618 		struct kobj_attribute *attr, const char *buf, size_t count)
619 {
620 	struct damon_sysfs_quotas *quotas = container_of(kobj,
621 			struct damon_sysfs_quotas, kobj);
622 	int err = kstrtoul(buf, 0, &quotas->sz);
623 
624 	if (err)
625 		return -EINVAL;
626 	return count;
627 }
628 
629 static ssize_t reset_interval_ms_show(struct kobject *kobj,
630 		struct kobj_attribute *attr, char *buf)
631 {
632 	struct damon_sysfs_quotas *quotas = container_of(kobj,
633 			struct damon_sysfs_quotas, kobj);
634 
635 	return sysfs_emit(buf, "%lu\n", quotas->reset_interval_ms);
636 }
637 
638 static ssize_t reset_interval_ms_store(struct kobject *kobj,
639 		struct kobj_attribute *attr, const char *buf, size_t count)
640 {
641 	struct damon_sysfs_quotas *quotas = container_of(kobj,
642 			struct damon_sysfs_quotas, kobj);
643 	int err = kstrtoul(buf, 0, &quotas->reset_interval_ms);
644 
645 	if (err)
646 		return -EINVAL;
647 	return count;
648 }
649 
650 static void damon_sysfs_quotas_release(struct kobject *kobj)
651 {
652 	kfree(container_of(kobj, struct damon_sysfs_quotas, kobj));
653 }
654 
655 static struct kobj_attribute damon_sysfs_quotas_ms_attr =
656 		__ATTR_RW_MODE(ms, 0600);
657 
658 static struct kobj_attribute damon_sysfs_quotas_sz_attr =
659 		__ATTR_RW_MODE(bytes, 0600);
660 
661 static struct kobj_attribute damon_sysfs_quotas_reset_interval_ms_attr =
662 		__ATTR_RW_MODE(reset_interval_ms, 0600);
663 
664 static struct attribute *damon_sysfs_quotas_attrs[] = {
665 	&damon_sysfs_quotas_ms_attr.attr,
666 	&damon_sysfs_quotas_sz_attr.attr,
667 	&damon_sysfs_quotas_reset_interval_ms_attr.attr,
668 	NULL,
669 };
670 ATTRIBUTE_GROUPS(damon_sysfs_quotas);
671 
672 static struct kobj_type damon_sysfs_quotas_ktype = {
673 	.release = damon_sysfs_quotas_release,
674 	.sysfs_ops = &kobj_sysfs_ops,
675 	.default_groups = damon_sysfs_quotas_groups,
676 };
677 
678 /*
679  * access_pattern directory
680  */
681 
682 struct damon_sysfs_access_pattern {
683 	struct kobject kobj;
684 	struct damon_sysfs_ul_range *sz;
685 	struct damon_sysfs_ul_range *nr_accesses;
686 	struct damon_sysfs_ul_range *age;
687 };
688 
689 static
690 struct damon_sysfs_access_pattern *damon_sysfs_access_pattern_alloc(void)
691 {
692 	struct damon_sysfs_access_pattern *access_pattern =
693 		kmalloc(sizeof(*access_pattern), GFP_KERNEL);
694 
695 	if (!access_pattern)
696 		return NULL;
697 	access_pattern->kobj = (struct kobject){};
698 	return access_pattern;
699 }
700 
701 static int damon_sysfs_access_pattern_add_range_dir(
702 		struct damon_sysfs_access_pattern *access_pattern,
703 		struct damon_sysfs_ul_range **range_dir_ptr,
704 		char *name)
705 {
706 	struct damon_sysfs_ul_range *range = damon_sysfs_ul_range_alloc(0, 0);
707 	int err;
708 
709 	if (!range)
710 		return -ENOMEM;
711 	err = kobject_init_and_add(&range->kobj, &damon_sysfs_ul_range_ktype,
712 			&access_pattern->kobj, name);
713 	if (err)
714 		kobject_put(&range->kobj);
715 	else
716 		*range_dir_ptr = range;
717 	return err;
718 }
719 
720 static int damon_sysfs_access_pattern_add_dirs(
721 		struct damon_sysfs_access_pattern *access_pattern)
722 {
723 	int err;
724 
725 	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
726 			&access_pattern->sz, "sz");
727 	if (err)
728 		goto put_sz_out;
729 
730 	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
731 			&access_pattern->nr_accesses, "nr_accesses");
732 	if (err)
733 		goto put_nr_accesses_sz_out;
734 
735 	err = damon_sysfs_access_pattern_add_range_dir(access_pattern,
736 			&access_pattern->age, "age");
737 	if (err)
738 		goto put_age_nr_accesses_sz_out;
739 	return 0;
740 
741 put_age_nr_accesses_sz_out:
742 	kobject_put(&access_pattern->age->kobj);
743 	access_pattern->age = NULL;
744 put_nr_accesses_sz_out:
745 	kobject_put(&access_pattern->nr_accesses->kobj);
746 	access_pattern->nr_accesses = NULL;
747 put_sz_out:
748 	kobject_put(&access_pattern->sz->kobj);
749 	access_pattern->sz = NULL;
750 	return err;
751 }
752 
753 static void damon_sysfs_access_pattern_rm_dirs(
754 		struct damon_sysfs_access_pattern *access_pattern)
755 {
756 	kobject_put(&access_pattern->sz->kobj);
757 	kobject_put(&access_pattern->nr_accesses->kobj);
758 	kobject_put(&access_pattern->age->kobj);
759 }
760 
761 static void damon_sysfs_access_pattern_release(struct kobject *kobj)
762 {
763 	kfree(container_of(kobj, struct damon_sysfs_access_pattern, kobj));
764 }
765 
766 static struct attribute *damon_sysfs_access_pattern_attrs[] = {
767 	NULL,
768 };
769 ATTRIBUTE_GROUPS(damon_sysfs_access_pattern);
770 
771 static struct kobj_type damon_sysfs_access_pattern_ktype = {
772 	.release = damon_sysfs_access_pattern_release,
773 	.sysfs_ops = &kobj_sysfs_ops,
774 	.default_groups = damon_sysfs_access_pattern_groups,
775 };
776 
777 /*
778  * scheme directory
779  */
780 
781 struct damon_sysfs_scheme {
782 	struct kobject kobj;
783 	enum damos_action action;
784 	struct damon_sysfs_access_pattern *access_pattern;
785 	struct damon_sysfs_quotas *quotas;
786 	struct damon_sysfs_watermarks *watermarks;
787 	struct damon_sysfs_stats *stats;
788 	struct damon_sysfs_scheme_regions *tried_regions;
789 };
790 
791 /* This should match with enum damos_action */
792 static const char * const damon_sysfs_damos_action_strs[] = {
793 	"willneed",
794 	"cold",
795 	"pageout",
796 	"hugepage",
797 	"nohugepage",
798 	"lru_prio",
799 	"lru_deprio",
800 	"stat",
801 };
802 
803 static struct damon_sysfs_scheme *damon_sysfs_scheme_alloc(
804 		enum damos_action action)
805 {
806 	struct damon_sysfs_scheme *scheme = kmalloc(sizeof(*scheme),
807 				GFP_KERNEL);
808 
809 	if (!scheme)
810 		return NULL;
811 	scheme->kobj = (struct kobject){};
812 	scheme->action = action;
813 	return scheme;
814 }
815 
816 static int damon_sysfs_scheme_set_access_pattern(
817 		struct damon_sysfs_scheme *scheme)
818 {
819 	struct damon_sysfs_access_pattern *access_pattern;
820 	int err;
821 
822 	access_pattern = damon_sysfs_access_pattern_alloc();
823 	if (!access_pattern)
824 		return -ENOMEM;
825 	err = kobject_init_and_add(&access_pattern->kobj,
826 			&damon_sysfs_access_pattern_ktype, &scheme->kobj,
827 			"access_pattern");
828 	if (err)
829 		goto out;
830 	err = damon_sysfs_access_pattern_add_dirs(access_pattern);
831 	if (err)
832 		goto out;
833 	scheme->access_pattern = access_pattern;
834 	return 0;
835 
836 out:
837 	kobject_put(&access_pattern->kobj);
838 	return err;
839 }
840 
841 static int damon_sysfs_scheme_set_quotas(struct damon_sysfs_scheme *scheme)
842 {
843 	struct damon_sysfs_quotas *quotas = damon_sysfs_quotas_alloc();
844 	int err;
845 
846 	if (!quotas)
847 		return -ENOMEM;
848 	err = kobject_init_and_add(&quotas->kobj, &damon_sysfs_quotas_ktype,
849 			&scheme->kobj, "quotas");
850 	if (err)
851 		goto out;
852 	err = damon_sysfs_quotas_add_dirs(quotas);
853 	if (err)
854 		goto out;
855 	scheme->quotas = quotas;
856 	return 0;
857 
858 out:
859 	kobject_put(&quotas->kobj);
860 	return err;
861 }
862 
863 static int damon_sysfs_scheme_set_watermarks(struct damon_sysfs_scheme *scheme)
864 {
865 	struct damon_sysfs_watermarks *watermarks =
866 		damon_sysfs_watermarks_alloc(DAMOS_WMARK_NONE, 0, 0, 0, 0);
867 	int err;
868 
869 	if (!watermarks)
870 		return -ENOMEM;
871 	err = kobject_init_and_add(&watermarks->kobj,
872 			&damon_sysfs_watermarks_ktype, &scheme->kobj,
873 			"watermarks");
874 	if (err)
875 		kobject_put(&watermarks->kobj);
876 	else
877 		scheme->watermarks = watermarks;
878 	return err;
879 }
880 
881 static int damon_sysfs_scheme_set_stats(struct damon_sysfs_scheme *scheme)
882 {
883 	struct damon_sysfs_stats *stats = damon_sysfs_stats_alloc();
884 	int err;
885 
886 	if (!stats)
887 		return -ENOMEM;
888 	err = kobject_init_and_add(&stats->kobj, &damon_sysfs_stats_ktype,
889 			&scheme->kobj, "stats");
890 	if (err)
891 		kobject_put(&stats->kobj);
892 	else
893 		scheme->stats = stats;
894 	return err;
895 }
896 
897 static int damon_sysfs_scheme_set_tried_regions(
898 		struct damon_sysfs_scheme *scheme)
899 {
900 	struct damon_sysfs_scheme_regions *tried_regions =
901 		damon_sysfs_scheme_regions_alloc();
902 	int err;
903 
904 	if (!tried_regions)
905 		return -ENOMEM;
906 	err = kobject_init_and_add(&tried_regions->kobj,
907 			&damon_sysfs_scheme_regions_ktype, &scheme->kobj,
908 			"tried_regions");
909 	if (err)
910 		kobject_put(&tried_regions->kobj);
911 	else
912 		scheme->tried_regions = tried_regions;
913 	return err;
914 }
915 
916 static int damon_sysfs_scheme_add_dirs(struct damon_sysfs_scheme *scheme)
917 {
918 	int err;
919 
920 	err = damon_sysfs_scheme_set_access_pattern(scheme);
921 	if (err)
922 		return err;
923 	err = damon_sysfs_scheme_set_quotas(scheme);
924 	if (err)
925 		goto put_access_pattern_out;
926 	err = damon_sysfs_scheme_set_watermarks(scheme);
927 	if (err)
928 		goto put_quotas_access_pattern_out;
929 	err = damon_sysfs_scheme_set_stats(scheme);
930 	if (err)
931 		goto put_watermarks_quotas_access_pattern_out;
932 	err = damon_sysfs_scheme_set_tried_regions(scheme);
933 	if (err)
934 		goto put_tried_regions_out;
935 	return 0;
936 
937 put_tried_regions_out:
938 	kobject_put(&scheme->tried_regions->kobj);
939 	scheme->tried_regions = NULL;
940 put_watermarks_quotas_access_pattern_out:
941 	kobject_put(&scheme->watermarks->kobj);
942 	scheme->watermarks = NULL;
943 put_quotas_access_pattern_out:
944 	kobject_put(&scheme->quotas->kobj);
945 	scheme->quotas = NULL;
946 put_access_pattern_out:
947 	kobject_put(&scheme->access_pattern->kobj);
948 	scheme->access_pattern = NULL;
949 	return err;
950 }
951 
952 static void damon_sysfs_scheme_rm_dirs(struct damon_sysfs_scheme *scheme)
953 {
954 	damon_sysfs_access_pattern_rm_dirs(scheme->access_pattern);
955 	kobject_put(&scheme->access_pattern->kobj);
956 	damon_sysfs_quotas_rm_dirs(scheme->quotas);
957 	kobject_put(&scheme->quotas->kobj);
958 	kobject_put(&scheme->watermarks->kobj);
959 	kobject_put(&scheme->stats->kobj);
960 	damon_sysfs_scheme_regions_rm_dirs(scheme->tried_regions);
961 	kobject_put(&scheme->tried_regions->kobj);
962 }
963 
964 static ssize_t action_show(struct kobject *kobj, struct kobj_attribute *attr,
965 		char *buf)
966 {
967 	struct damon_sysfs_scheme *scheme = container_of(kobj,
968 			struct damon_sysfs_scheme, kobj);
969 
970 	return sysfs_emit(buf, "%s\n",
971 			damon_sysfs_damos_action_strs[scheme->action]);
972 }
973 
974 static ssize_t action_store(struct kobject *kobj, struct kobj_attribute *attr,
975 		const char *buf, size_t count)
976 {
977 	struct damon_sysfs_scheme *scheme = container_of(kobj,
978 			struct damon_sysfs_scheme, kobj);
979 	enum damos_action action;
980 
981 	for (action = 0; action < NR_DAMOS_ACTIONS; action++) {
982 		if (sysfs_streq(buf, damon_sysfs_damos_action_strs[action])) {
983 			scheme->action = action;
984 			return count;
985 		}
986 	}
987 	return -EINVAL;
988 }
989 
990 static void damon_sysfs_scheme_release(struct kobject *kobj)
991 {
992 	kfree(container_of(kobj, struct damon_sysfs_scheme, kobj));
993 }
994 
995 static struct kobj_attribute damon_sysfs_scheme_action_attr =
996 		__ATTR_RW_MODE(action, 0600);
997 
998 static struct attribute *damon_sysfs_scheme_attrs[] = {
999 	&damon_sysfs_scheme_action_attr.attr,
1000 	NULL,
1001 };
1002 ATTRIBUTE_GROUPS(damon_sysfs_scheme);
1003 
1004 static struct kobj_type damon_sysfs_scheme_ktype = {
1005 	.release = damon_sysfs_scheme_release,
1006 	.sysfs_ops = &kobj_sysfs_ops,
1007 	.default_groups = damon_sysfs_scheme_groups,
1008 };
1009 
1010 /*
1011  * schemes directory
1012  */
1013 
1014 struct damon_sysfs_schemes *damon_sysfs_schemes_alloc(void)
1015 {
1016 	return kzalloc(sizeof(struct damon_sysfs_schemes), GFP_KERNEL);
1017 }
1018 
1019 void damon_sysfs_schemes_rm_dirs(struct damon_sysfs_schemes *schemes)
1020 {
1021 	struct damon_sysfs_scheme **schemes_arr = schemes->schemes_arr;
1022 	int i;
1023 
1024 	for (i = 0; i < schemes->nr; i++) {
1025 		damon_sysfs_scheme_rm_dirs(schemes_arr[i]);
1026 		kobject_put(&schemes_arr[i]->kobj);
1027 	}
1028 	schemes->nr = 0;
1029 	kfree(schemes_arr);
1030 	schemes->schemes_arr = NULL;
1031 }
1032 
1033 static int damon_sysfs_schemes_add_dirs(struct damon_sysfs_schemes *schemes,
1034 		int nr_schemes)
1035 {
1036 	struct damon_sysfs_scheme **schemes_arr, *scheme;
1037 	int err, i;
1038 
1039 	damon_sysfs_schemes_rm_dirs(schemes);
1040 	if (!nr_schemes)
1041 		return 0;
1042 
1043 	schemes_arr = kmalloc_array(nr_schemes, sizeof(*schemes_arr),
1044 			GFP_KERNEL | __GFP_NOWARN);
1045 	if (!schemes_arr)
1046 		return -ENOMEM;
1047 	schemes->schemes_arr = schemes_arr;
1048 
1049 	for (i = 0; i < nr_schemes; i++) {
1050 		scheme = damon_sysfs_scheme_alloc(DAMOS_STAT);
1051 		if (!scheme) {
1052 			damon_sysfs_schemes_rm_dirs(schemes);
1053 			return -ENOMEM;
1054 		}
1055 
1056 		err = kobject_init_and_add(&scheme->kobj,
1057 				&damon_sysfs_scheme_ktype, &schemes->kobj,
1058 				"%d", i);
1059 		if (err)
1060 			goto out;
1061 		err = damon_sysfs_scheme_add_dirs(scheme);
1062 		if (err)
1063 			goto out;
1064 
1065 		schemes_arr[i] = scheme;
1066 		schemes->nr++;
1067 	}
1068 	return 0;
1069 
1070 out:
1071 	damon_sysfs_schemes_rm_dirs(schemes);
1072 	kobject_put(&scheme->kobj);
1073 	return err;
1074 }
1075 
1076 static ssize_t nr_schemes_show(struct kobject *kobj,
1077 		struct kobj_attribute *attr, char *buf)
1078 {
1079 	struct damon_sysfs_schemes *schemes = container_of(kobj,
1080 			struct damon_sysfs_schemes, kobj);
1081 
1082 	return sysfs_emit(buf, "%d\n", schemes->nr);
1083 }
1084 
1085 static ssize_t nr_schemes_store(struct kobject *kobj,
1086 		struct kobj_attribute *attr, const char *buf, size_t count)
1087 {
1088 	struct damon_sysfs_schemes *schemes;
1089 	int nr, err = kstrtoint(buf, 0, &nr);
1090 
1091 	if (err)
1092 		return err;
1093 	if (nr < 0)
1094 		return -EINVAL;
1095 
1096 	schemes = container_of(kobj, struct damon_sysfs_schemes, kobj);
1097 
1098 	if (!mutex_trylock(&damon_sysfs_lock))
1099 		return -EBUSY;
1100 	err = damon_sysfs_schemes_add_dirs(schemes, nr);
1101 	mutex_unlock(&damon_sysfs_lock);
1102 	if (err)
1103 		return err;
1104 	return count;
1105 }
1106 
1107 static void damon_sysfs_schemes_release(struct kobject *kobj)
1108 {
1109 	kfree(container_of(kobj, struct damon_sysfs_schemes, kobj));
1110 }
1111 
1112 static struct kobj_attribute damon_sysfs_schemes_nr_attr =
1113 		__ATTR_RW_MODE(nr_schemes, 0600);
1114 
1115 static struct attribute *damon_sysfs_schemes_attrs[] = {
1116 	&damon_sysfs_schemes_nr_attr.attr,
1117 	NULL,
1118 };
1119 ATTRIBUTE_GROUPS(damon_sysfs_schemes);
1120 
1121 struct kobj_type damon_sysfs_schemes_ktype = {
1122 	.release = damon_sysfs_schemes_release,
1123 	.sysfs_ops = &kobj_sysfs_ops,
1124 	.default_groups = damon_sysfs_schemes_groups,
1125 };
1126 
1127 static struct damos *damon_sysfs_mk_scheme(
1128 		struct damon_sysfs_scheme *sysfs_scheme)
1129 {
1130 	struct damon_sysfs_access_pattern *access_pattern =
1131 		sysfs_scheme->access_pattern;
1132 	struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1133 	struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1134 	struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1135 
1136 	struct damos_access_pattern pattern = {
1137 		.min_sz_region = access_pattern->sz->min,
1138 		.max_sz_region = access_pattern->sz->max,
1139 		.min_nr_accesses = access_pattern->nr_accesses->min,
1140 		.max_nr_accesses = access_pattern->nr_accesses->max,
1141 		.min_age_region = access_pattern->age->min,
1142 		.max_age_region = access_pattern->age->max,
1143 	};
1144 	struct damos_quota quota = {
1145 		.ms = sysfs_quotas->ms,
1146 		.sz = sysfs_quotas->sz,
1147 		.reset_interval = sysfs_quotas->reset_interval_ms,
1148 		.weight_sz = sysfs_weights->sz,
1149 		.weight_nr_accesses = sysfs_weights->nr_accesses,
1150 		.weight_age = sysfs_weights->age,
1151 	};
1152 	struct damos_watermarks wmarks = {
1153 		.metric = sysfs_wmarks->metric,
1154 		.interval = sysfs_wmarks->interval_us,
1155 		.high = sysfs_wmarks->high,
1156 		.mid = sysfs_wmarks->mid,
1157 		.low = sysfs_wmarks->low,
1158 	};
1159 
1160 	return damon_new_scheme(&pattern, sysfs_scheme->action, &quota,
1161 			&wmarks);
1162 }
1163 
1164 static void damon_sysfs_update_scheme(struct damos *scheme,
1165 		struct damon_sysfs_scheme *sysfs_scheme)
1166 {
1167 	struct damon_sysfs_access_pattern *access_pattern =
1168 		sysfs_scheme->access_pattern;
1169 	struct damon_sysfs_quotas *sysfs_quotas = sysfs_scheme->quotas;
1170 	struct damon_sysfs_weights *sysfs_weights = sysfs_quotas->weights;
1171 	struct damon_sysfs_watermarks *sysfs_wmarks = sysfs_scheme->watermarks;
1172 
1173 	scheme->pattern.min_sz_region = access_pattern->sz->min;
1174 	scheme->pattern.max_sz_region = access_pattern->sz->max;
1175 	scheme->pattern.min_nr_accesses = access_pattern->nr_accesses->min;
1176 	scheme->pattern.max_nr_accesses = access_pattern->nr_accesses->max;
1177 	scheme->pattern.min_age_region = access_pattern->age->min;
1178 	scheme->pattern.max_age_region = access_pattern->age->max;
1179 
1180 	scheme->action = sysfs_scheme->action;
1181 
1182 	scheme->quota.ms = sysfs_quotas->ms;
1183 	scheme->quota.sz = sysfs_quotas->sz;
1184 	scheme->quota.reset_interval = sysfs_quotas->reset_interval_ms;
1185 	scheme->quota.weight_sz = sysfs_weights->sz;
1186 	scheme->quota.weight_nr_accesses = sysfs_weights->nr_accesses;
1187 	scheme->quota.weight_age = sysfs_weights->age;
1188 
1189 	scheme->wmarks.metric = sysfs_wmarks->metric;
1190 	scheme->wmarks.interval = sysfs_wmarks->interval_us;
1191 	scheme->wmarks.high = sysfs_wmarks->high;
1192 	scheme->wmarks.mid = sysfs_wmarks->mid;
1193 	scheme->wmarks.low = sysfs_wmarks->low;
1194 }
1195 
1196 int damon_sysfs_set_schemes(struct damon_ctx *ctx,
1197 		struct damon_sysfs_schemes *sysfs_schemes)
1198 {
1199 	struct damos *scheme, *next;
1200 	int i = 0;
1201 
1202 	damon_for_each_scheme_safe(scheme, next, ctx) {
1203 		if (i < sysfs_schemes->nr)
1204 			damon_sysfs_update_scheme(scheme,
1205 					sysfs_schemes->schemes_arr[i]);
1206 		else
1207 			damon_destroy_scheme(scheme);
1208 		i++;
1209 	}
1210 
1211 	for (; i < sysfs_schemes->nr; i++) {
1212 		struct damos *scheme, *next;
1213 
1214 		scheme = damon_sysfs_mk_scheme(sysfs_schemes->schemes_arr[i]);
1215 		if (!scheme) {
1216 			damon_for_each_scheme_safe(scheme, next, ctx)
1217 				damon_destroy_scheme(scheme);
1218 			return -ENOMEM;
1219 		}
1220 		damon_add_scheme(ctx, scheme);
1221 	}
1222 	return 0;
1223 }
1224 
1225 void damon_sysfs_schemes_update_stats(
1226 		struct damon_sysfs_schemes *sysfs_schemes,
1227 		struct damon_ctx *ctx)
1228 {
1229 	struct damos *scheme;
1230 	int schemes_idx = 0;
1231 
1232 	damon_for_each_scheme(scheme, ctx) {
1233 		struct damon_sysfs_stats *sysfs_stats;
1234 
1235 		/* user could have removed the scheme sysfs dir */
1236 		if (schemes_idx >= sysfs_schemes->nr)
1237 			break;
1238 
1239 		sysfs_stats = sysfs_schemes->schemes_arr[schemes_idx++]->stats;
1240 		sysfs_stats->nr_tried = scheme->stat.nr_tried;
1241 		sysfs_stats->sz_tried = scheme->stat.sz_tried;
1242 		sysfs_stats->nr_applied = scheme->stat.nr_applied;
1243 		sysfs_stats->sz_applied = scheme->stat.sz_applied;
1244 		sysfs_stats->qt_exceeds = scheme->stat.qt_exceeds;
1245 	}
1246 }
1247 
1248 /*
1249  * damon_sysfs_schemes that need to update its schemes regions dir.  Protected
1250  * by damon_sysfs_lock
1251  */
1252 static struct damon_sysfs_schemes *damon_sysfs_schemes_for_damos_callback;
1253 static int damon_sysfs_schemes_region_idx;
1254 
1255 /*
1256  * DAMON callback that called before damos apply.  While this callback is
1257  * registered, damon_sysfs_lock should be held to ensure the regions
1258  * directories exist.
1259  */
1260 static int damon_sysfs_before_damos_apply(struct damon_ctx *ctx,
1261 		struct damon_target *t, struct damon_region *r,
1262 		struct damos *s)
1263 {
1264 	struct damos *scheme;
1265 	struct damon_sysfs_scheme_regions *sysfs_regions;
1266 	struct damon_sysfs_scheme_region *region;
1267 	struct damon_sysfs_schemes *sysfs_schemes =
1268 		damon_sysfs_schemes_for_damos_callback;
1269 	int schemes_idx = 0;
1270 
1271 	damon_for_each_scheme(scheme, ctx) {
1272 		if (scheme == s)
1273 			break;
1274 		schemes_idx++;
1275 	}
1276 
1277 	/* user could have removed the scheme sysfs dir */
1278 	if (schemes_idx >= sysfs_schemes->nr)
1279 		return 0;
1280 
1281 	sysfs_regions = sysfs_schemes->schemes_arr[schemes_idx]->tried_regions;
1282 	region = damon_sysfs_scheme_region_alloc(r);
1283 	list_add_tail(&region->list, &sysfs_regions->regions_list);
1284 	sysfs_regions->nr_regions++;
1285 	if (kobject_init_and_add(&region->kobj,
1286 				&damon_sysfs_scheme_region_ktype,
1287 				&sysfs_regions->kobj, "%d",
1288 				damon_sysfs_schemes_region_idx++)) {
1289 		kobject_put(&region->kobj);
1290 	}
1291 	return 0;
1292 }
1293 
1294 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1295 int damon_sysfs_schemes_clear_regions(
1296 		struct damon_sysfs_schemes *sysfs_schemes,
1297 		struct damon_ctx *ctx)
1298 {
1299 	struct damos *scheme;
1300 	int schemes_idx = 0;
1301 
1302 	damon_for_each_scheme(scheme, ctx) {
1303 		struct damon_sysfs_scheme *sysfs_scheme;
1304 
1305 		/* user could have removed the scheme sysfs dir */
1306 		if (schemes_idx >= sysfs_schemes->nr)
1307 			break;
1308 
1309 		sysfs_scheme = sysfs_schemes->schemes_arr[schemes_idx++];
1310 		damon_sysfs_scheme_regions_rm_dirs(
1311 				sysfs_scheme->tried_regions);
1312 	}
1313 	return 0;
1314 }
1315 
1316 /* Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock */
1317 int damon_sysfs_schemes_update_regions_start(
1318 		struct damon_sysfs_schemes *sysfs_schemes,
1319 		struct damon_ctx *ctx)
1320 {
1321 	damon_sysfs_schemes_clear_regions(sysfs_schemes, ctx);
1322 	damon_sysfs_schemes_for_damos_callback = sysfs_schemes;
1323 	ctx->callback.before_damos_apply = damon_sysfs_before_damos_apply;
1324 	return 0;
1325 }
1326 
1327 /*
1328  * Called from damon_sysfs_cmd_request_callback under damon_sysfs_lock.  Caller
1329  * should unlock damon_sysfs_lock which held before
1330  * damon_sysfs_schemes_update_regions_start()
1331  */
1332 int damon_sysfs_schemes_update_regions_stop(struct damon_ctx *ctx)
1333 {
1334 	damon_sysfs_schemes_for_damos_callback = NULL;
1335 	ctx->callback.before_damos_apply = NULL;
1336 	damon_sysfs_schemes_region_idx = 0;
1337 	return 0;
1338 }
1339