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