1 // SPDX-License-Identifier: GPL-2.0
3 * DAMON Debugfs Interface
5 * Author: SeongJae Park <sj@kernel.org>
8 #define pr_fmt(fmt) "damon-dbgfs: " fmt
10 #include <linux/damon.h>
11 #include <linux/debugfs.h>
12 #include <linux/file.h>
14 #include <linux/module.h>
15 #include <linux/page_idle.h>
16 #include <linux/slab.h>
18 #define DAMON_DBGFS_DEPRECATION_NOTICE \
19 "DAMON debugfs interface is deprecated, so users should move " \
20 "to DAMON_SYSFS. If you cannot, please report your usecase to " \
21 "damon@lists.linux.dev and linux-mm@kvack.org.\n"
23 static struct damon_ctx
**dbgfs_ctxs
;
24 static int dbgfs_nr_ctxs
;
25 static struct dentry
**dbgfs_dirs
;
26 static DEFINE_MUTEX(damon_dbgfs_lock
);
28 static void damon_dbgfs_warn_deprecation(void)
30 pr_warn_once(DAMON_DBGFS_DEPRECATION_NOTICE
);
34 * Returns non-empty string on success, negative error code otherwise.
36 static char *user_input_str(const char __user
*buf
, size_t count
, loff_t
*ppos
)
41 /* We do not accept continuous write */
43 return ERR_PTR(-EINVAL
);
45 kbuf
= kmalloc(count
+ 1, GFP_KERNEL
| __GFP_NOWARN
);
47 return ERR_PTR(-ENOMEM
);
49 ret
= simple_write_to_buffer(kbuf
, count
+ 1, ppos
, buf
, count
);
59 static ssize_t
dbgfs_attrs_read(struct file
*file
,
60 char __user
*buf
, size_t count
, loff_t
*ppos
)
62 struct damon_ctx
*ctx
= file
->private_data
;
66 mutex_lock(&ctx
->kdamond_lock
);
67 ret
= scnprintf(kbuf
, ARRAY_SIZE(kbuf
), "%lu %lu %lu %lu %lu\n",
68 ctx
->attrs
.sample_interval
, ctx
->attrs
.aggr_interval
,
69 ctx
->attrs
.ops_update_interval
,
70 ctx
->attrs
.min_nr_regions
, ctx
->attrs
.max_nr_regions
);
71 mutex_unlock(&ctx
->kdamond_lock
);
73 return simple_read_from_buffer(buf
, count
, ppos
, kbuf
, ret
);
76 static ssize_t
dbgfs_attrs_write(struct file
*file
,
77 const char __user
*buf
, size_t count
, loff_t
*ppos
)
79 struct damon_ctx
*ctx
= file
->private_data
;
80 struct damon_attrs attrs
;
84 kbuf
= user_input_str(buf
, count
, ppos
);
88 if (sscanf(kbuf
, "%lu %lu %lu %lu %lu",
89 &attrs
.sample_interval
, &attrs
.aggr_interval
,
90 &attrs
.ops_update_interval
,
91 &attrs
.min_nr_regions
,
92 &attrs
.max_nr_regions
) != 5) {
97 mutex_lock(&ctx
->kdamond_lock
);
103 ret
= damon_set_attrs(ctx
, &attrs
);
107 mutex_unlock(&ctx
->kdamond_lock
);
114 * Return corresponding dbgfs' scheme action value (int) for the given
115 * damos_action if the given damos_action value is valid and supported by
116 * dbgfs, negative error code otherwise.
118 static int damos_action_to_dbgfs_scheme_action(enum damos_action action
)
129 case DAMOS_NOHUGEPAGE
:
138 static ssize_t
sprint_schemes(struct damon_ctx
*c
, char *buf
, ssize_t len
)
144 damon_for_each_scheme(s
, c
) {
145 rc
= scnprintf(&buf
[written
], len
- written
,
146 "%lu %lu %u %u %u %u %d %lu %lu %lu %u %u %u %d %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
147 s
->pattern
.min_sz_region
,
148 s
->pattern
.max_sz_region
,
149 s
->pattern
.min_nr_accesses
,
150 s
->pattern
.max_nr_accesses
,
151 s
->pattern
.min_age_region
,
152 s
->pattern
.max_age_region
,
153 damos_action_to_dbgfs_scheme_action(s
->action
),
154 s
->quota
.ms
, s
->quota
.sz
,
155 s
->quota
.reset_interval
,
157 s
->quota
.weight_nr_accesses
,
159 s
->wmarks
.metric
, s
->wmarks
.interval
,
160 s
->wmarks
.high
, s
->wmarks
.mid
, s
->wmarks
.low
,
161 s
->stat
.nr_tried
, s
->stat
.sz_tried
,
162 s
->stat
.nr_applied
, s
->stat
.sz_applied
,
172 static ssize_t
dbgfs_schemes_read(struct file
*file
, char __user
*buf
,
173 size_t count
, loff_t
*ppos
)
175 struct damon_ctx
*ctx
= file
->private_data
;
179 kbuf
= kmalloc(count
, GFP_KERNEL
| __GFP_NOWARN
);
183 mutex_lock(&ctx
->kdamond_lock
);
184 len
= sprint_schemes(ctx
, kbuf
, count
);
185 mutex_unlock(&ctx
->kdamond_lock
);
188 len
= simple_read_from_buffer(buf
, count
, ppos
, kbuf
, len
);
195 static void free_schemes_arr(struct damos
**schemes
, ssize_t nr_schemes
)
199 for (i
= 0; i
< nr_schemes
; i
++)
205 * Return corresponding damos_action for the given dbgfs input for a scheme
206 * action if the input is valid, negative error code otherwise.
208 static enum damos_action
dbgfs_scheme_action_to_damos_action(int dbgfs_action
)
210 switch (dbgfs_action
) {
212 return DAMOS_WILLNEED
;
216 return DAMOS_PAGEOUT
;
218 return DAMOS_HUGEPAGE
;
220 return DAMOS_NOHUGEPAGE
;
229 * Converts a string into an array of struct damos pointers
231 * Returns an array of struct damos pointers that converted if the conversion
232 * success, or NULL otherwise.
234 static struct damos
**str_to_schemes(const char *str
, ssize_t len
,
237 struct damos
*scheme
, **schemes
;
238 const int max_nr_schemes
= 256;
239 int pos
= 0, parsed
, ret
;
240 unsigned int action_input
;
241 enum damos_action action
;
243 schemes
= kmalloc_array(max_nr_schemes
, sizeof(scheme
),
249 while (pos
< len
&& *nr_schemes
< max_nr_schemes
) {
250 struct damos_access_pattern pattern
= {};
251 struct damos_quota quota
= {};
252 struct damos_watermarks wmarks
;
254 ret
= sscanf(&str
[pos
],
255 "%lu %lu %u %u %u %u %u %lu %lu %lu %u %u %u %u %lu %lu %lu %lu%n",
256 &pattern
.min_sz_region
, &pattern
.max_sz_region
,
257 &pattern
.min_nr_accesses
,
258 &pattern
.max_nr_accesses
,
259 &pattern
.min_age_region
,
260 &pattern
.max_age_region
,
261 &action_input
, "a
.ms
,
262 "a
.sz
, "a
.reset_interval
,
263 "a
.weight_sz
, "a
.weight_nr_accesses
,
264 "a
.weight_age
, &wmarks
.metric
,
265 &wmarks
.interval
, &wmarks
.high
, &wmarks
.mid
,
266 &wmarks
.low
, &parsed
);
269 action
= dbgfs_scheme_action_to_damos_action(action_input
);
273 if (pattern
.min_sz_region
> pattern
.max_sz_region
||
274 pattern
.min_nr_accesses
> pattern
.max_nr_accesses
||
275 pattern
.min_age_region
> pattern
.max_age_region
)
278 if (wmarks
.high
< wmarks
.mid
|| wmarks
.high
< wmarks
.low
||
279 wmarks
.mid
< wmarks
.low
)
283 scheme
= damon_new_scheme(&pattern
, action
, 0, "a
,
284 &wmarks
, NUMA_NO_NODE
);
288 schemes
[*nr_schemes
] = scheme
;
293 free_schemes_arr(schemes
, *nr_schemes
);
297 static ssize_t
dbgfs_schemes_write(struct file
*file
, const char __user
*buf
,
298 size_t count
, loff_t
*ppos
)
300 struct damon_ctx
*ctx
= file
->private_data
;
302 struct damos
**schemes
;
303 ssize_t nr_schemes
= 0, ret
;
305 kbuf
= user_input_str(buf
, count
, ppos
);
307 return PTR_ERR(kbuf
);
309 schemes
= str_to_schemes(kbuf
, count
, &nr_schemes
);
315 mutex_lock(&ctx
->kdamond_lock
);
321 damon_set_schemes(ctx
, schemes
, nr_schemes
);
326 mutex_unlock(&ctx
->kdamond_lock
);
327 free_schemes_arr(schemes
, nr_schemes
);
333 static ssize_t
sprint_target_ids(struct damon_ctx
*ctx
, char *buf
, ssize_t len
)
335 struct damon_target
*t
;
340 damon_for_each_target(t
, ctx
) {
341 if (damon_target_has_pid(ctx
))
342 /* Show pid numbers to debugfs users */
343 id
= pid_vnr(t
->pid
);
345 /* Show 42 for physical address space, just for fun */
348 rc
= scnprintf(&buf
[written
], len
- written
, "%d ", id
);
355 written
+= scnprintf(&buf
[written
], len
- written
, "\n");
359 static ssize_t
dbgfs_target_ids_read(struct file
*file
,
360 char __user
*buf
, size_t count
, loff_t
*ppos
)
362 struct damon_ctx
*ctx
= file
->private_data
;
366 mutex_lock(&ctx
->kdamond_lock
);
367 len
= sprint_target_ids(ctx
, ids_buf
, 320);
368 mutex_unlock(&ctx
->kdamond_lock
);
372 return simple_read_from_buffer(buf
, count
, ppos
, ids_buf
, len
);
376 * Converts a string into an integers array
378 * Returns an array of integers array if the conversion success, or NULL
381 static int *str_to_ints(const char *str
, ssize_t len
, ssize_t
*nr_ints
)
384 const int max_nr_ints
= 32;
386 int pos
= 0, parsed
, ret
;
389 array
= kmalloc_array(max_nr_ints
, sizeof(*array
), GFP_KERNEL
);
392 while (*nr_ints
< max_nr_ints
&& pos
< len
) {
393 ret
= sscanf(&str
[pos
], "%d%n", &nr
, &parsed
);
397 array
[*nr_ints
] = nr
;
404 static void dbgfs_put_pids(struct pid
**pids
, int nr_pids
)
408 for (i
= 0; i
< nr_pids
; i
++)
413 * Converts a string into an struct pid pointers array
415 * Returns an array of struct pid pointers if the conversion success, or NULL
418 static struct pid
**str_to_pids(const char *str
, ssize_t len
, ssize_t
*nr_pids
)
426 ints
= str_to_ints(str
, len
, &nr_ints
);
430 pids
= kmalloc_array(nr_ints
, sizeof(*pids
), GFP_KERNEL
);
434 for (; *nr_pids
< nr_ints
; (*nr_pids
)++) {
435 pids
[*nr_pids
] = find_get_pid(ints
[*nr_pids
]);
436 if (!pids
[*nr_pids
]) {
437 dbgfs_put_pids(pids
, *nr_pids
);
450 * dbgfs_set_targets() - Set monitoring targets.
451 * @ctx: monitoring context
452 * @nr_targets: number of targets
453 * @pids: array of target pids (size is same to @nr_targets)
455 * This function should not be called while the kdamond is running. @pids is
456 * ignored if the context is not configured to have pid in each target. On
457 * failure, reference counts of all pids in @pids are decremented.
459 * Return: 0 on success, negative error code otherwise.
461 static int dbgfs_set_targets(struct damon_ctx
*ctx
, ssize_t nr_targets
,
465 struct damon_target
*t
, *next
;
467 damon_for_each_target_safe(t
, next
, ctx
) {
468 if (damon_target_has_pid(ctx
))
470 damon_destroy_target(t
);
473 for (i
= 0; i
< nr_targets
; i
++) {
474 t
= damon_new_target();
476 damon_for_each_target_safe(t
, next
, ctx
)
477 damon_destroy_target(t
);
478 if (damon_target_has_pid(ctx
))
479 dbgfs_put_pids(pids
, nr_targets
);
482 if (damon_target_has_pid(ctx
))
484 damon_add_target(ctx
, t
);
490 static ssize_t
dbgfs_target_ids_write(struct file
*file
,
491 const char __user
*buf
, size_t count
, loff_t
*ppos
)
493 struct damon_ctx
*ctx
= file
->private_data
;
494 bool id_is_pid
= true;
496 struct pid
**target_pids
= NULL
;
500 kbuf
= user_input_str(buf
, count
, ppos
);
502 return PTR_ERR(kbuf
);
504 if (!strncmp(kbuf
, "paddr\n", count
)) {
510 target_pids
= str_to_pids(kbuf
, count
, &nr_targets
);
517 mutex_lock(&ctx
->kdamond_lock
);
520 dbgfs_put_pids(target_pids
, nr_targets
);
525 /* remove previously set targets */
526 dbgfs_set_targets(ctx
, 0, NULL
);
532 /* Configure the context for the address space type */
534 ret
= damon_select_ops(ctx
, DAMON_OPS_VADDR
);
536 ret
= damon_select_ops(ctx
, DAMON_OPS_PADDR
);
540 ret
= dbgfs_set_targets(ctx
, nr_targets
, target_pids
);
545 mutex_unlock(&ctx
->kdamond_lock
);
552 static ssize_t
sprint_init_regions(struct damon_ctx
*c
, char *buf
, ssize_t len
)
554 struct damon_target
*t
;
555 struct damon_region
*r
;
560 damon_for_each_target(t
, c
) {
561 damon_for_each_region(r
, t
) {
562 rc
= scnprintf(&buf
[written
], len
- written
,
564 target_idx
, r
->ar
.start
, r
->ar
.end
);
574 static ssize_t
dbgfs_init_regions_read(struct file
*file
, char __user
*buf
,
575 size_t count
, loff_t
*ppos
)
577 struct damon_ctx
*ctx
= file
->private_data
;
581 kbuf
= kmalloc(count
, GFP_KERNEL
| __GFP_NOWARN
);
585 mutex_lock(&ctx
->kdamond_lock
);
587 mutex_unlock(&ctx
->kdamond_lock
);
592 len
= sprint_init_regions(ctx
, kbuf
, count
);
593 mutex_unlock(&ctx
->kdamond_lock
);
596 len
= simple_read_from_buffer(buf
, count
, ppos
, kbuf
, len
);
603 static int add_init_region(struct damon_ctx
*c
, int target_idx
,
604 struct damon_addr_range
*ar
)
606 struct damon_target
*t
;
607 struct damon_region
*r
, *prev
;
608 unsigned long idx
= 0;
611 if (ar
->start
>= ar
->end
)
614 damon_for_each_target(t
, c
) {
615 if (idx
++ == target_idx
) {
616 r
= damon_new_region(ar
->start
, ar
->end
);
619 damon_add_region(r
, t
);
620 if (damon_nr_regions(t
) > 1) {
621 prev
= damon_prev_region(r
);
622 if (prev
->ar
.end
> r
->ar
.start
) {
623 damon_destroy_region(r
, t
);
633 static int set_init_regions(struct damon_ctx
*c
, const char *str
, ssize_t len
)
635 struct damon_target
*t
;
636 struct damon_region
*r
, *next
;
637 int pos
= 0, parsed
, ret
;
639 struct damon_addr_range ar
;
642 damon_for_each_target(t
, c
) {
643 damon_for_each_region_safe(r
, next
, t
)
644 damon_destroy_region(r
, t
);
648 ret
= sscanf(&str
[pos
], "%d %lu %lu%n",
649 &target_idx
, &ar
.start
, &ar
.end
, &parsed
);
652 err
= add_init_region(c
, target_idx
, &ar
);
661 damon_for_each_target(t
, c
) {
662 damon_for_each_region_safe(r
, next
, t
)
663 damon_destroy_region(r
, t
);
668 static ssize_t
dbgfs_init_regions_write(struct file
*file
,
669 const char __user
*buf
, size_t count
,
672 struct damon_ctx
*ctx
= file
->private_data
;
677 kbuf
= user_input_str(buf
, count
, ppos
);
679 return PTR_ERR(kbuf
);
681 mutex_lock(&ctx
->kdamond_lock
);
687 err
= set_init_regions(ctx
, kbuf
, ret
);
692 mutex_unlock(&ctx
->kdamond_lock
);
697 static ssize_t
dbgfs_kdamond_pid_read(struct file
*file
,
698 char __user
*buf
, size_t count
, loff_t
*ppos
)
700 struct damon_ctx
*ctx
= file
->private_data
;
704 kbuf
= kmalloc(count
, GFP_KERNEL
| __GFP_NOWARN
);
708 mutex_lock(&ctx
->kdamond_lock
);
710 len
= scnprintf(kbuf
, count
, "%d\n", ctx
->kdamond
->pid
);
712 len
= scnprintf(kbuf
, count
, "none\n");
713 mutex_unlock(&ctx
->kdamond_lock
);
716 len
= simple_read_from_buffer(buf
, count
, ppos
, kbuf
, len
);
723 static int damon_dbgfs_open(struct inode
*inode
, struct file
*file
)
725 damon_dbgfs_warn_deprecation();
727 file
->private_data
= inode
->i_private
;
729 return nonseekable_open(inode
, file
);
732 static const struct file_operations attrs_fops
= {
733 .open
= damon_dbgfs_open
,
734 .read
= dbgfs_attrs_read
,
735 .write
= dbgfs_attrs_write
,
738 static const struct file_operations schemes_fops
= {
739 .open
= damon_dbgfs_open
,
740 .read
= dbgfs_schemes_read
,
741 .write
= dbgfs_schemes_write
,
744 static const struct file_operations target_ids_fops
= {
745 .open
= damon_dbgfs_open
,
746 .read
= dbgfs_target_ids_read
,
747 .write
= dbgfs_target_ids_write
,
750 static const struct file_operations init_regions_fops
= {
751 .open
= damon_dbgfs_open
,
752 .read
= dbgfs_init_regions_read
,
753 .write
= dbgfs_init_regions_write
,
756 static const struct file_operations kdamond_pid_fops
= {
757 .open
= damon_dbgfs_open
,
758 .read
= dbgfs_kdamond_pid_read
,
761 static void dbgfs_fill_ctx_dir(struct dentry
*dir
, struct damon_ctx
*ctx
)
763 const char * const file_names
[] = {"attrs", "schemes", "target_ids",
764 "init_regions", "kdamond_pid"};
765 const struct file_operations
*fops
[] = {&attrs_fops
, &schemes_fops
,
766 &target_ids_fops
, &init_regions_fops
, &kdamond_pid_fops
};
769 for (i
= 0; i
< ARRAY_SIZE(file_names
); i
++)
770 debugfs_create_file(file_names
[i
], 0600, dir
, ctx
, fops
[i
]);
773 static void dbgfs_before_terminate(struct damon_ctx
*ctx
)
775 struct damon_target
*t
, *next
;
777 if (!damon_target_has_pid(ctx
))
780 mutex_lock(&ctx
->kdamond_lock
);
781 damon_for_each_target_safe(t
, next
, ctx
) {
783 damon_destroy_target(t
);
785 mutex_unlock(&ctx
->kdamond_lock
);
788 static struct damon_ctx
*dbgfs_new_ctx(void)
790 struct damon_ctx
*ctx
;
792 ctx
= damon_new_ctx();
796 if (damon_select_ops(ctx
, DAMON_OPS_VADDR
) &&
797 damon_select_ops(ctx
, DAMON_OPS_PADDR
)) {
798 damon_destroy_ctx(ctx
);
801 ctx
->callback
.before_terminate
= dbgfs_before_terminate
;
805 static void dbgfs_destroy_ctx(struct damon_ctx
*ctx
)
807 damon_destroy_ctx(ctx
);
810 static ssize_t
damon_dbgfs_deprecated_read(struct file
*file
,
811 char __user
*buf
, size_t count
, loff_t
*ppos
)
813 static const char kbuf
[512] = DAMON_DBGFS_DEPRECATION_NOTICE
;
815 return simple_read_from_buffer(buf
, count
, ppos
, kbuf
, strlen(kbuf
));
819 * Make a context of @name and create a debugfs directory for it.
821 * This function should be called while holding damon_dbgfs_lock.
823 * Returns 0 on success, negative error code otherwise.
825 static int dbgfs_mk_context(char *name
)
827 struct dentry
*root
, **new_dirs
, *new_dir
;
828 struct damon_ctx
**new_ctxs
, *new_ctx
;
830 if (damon_nr_running_ctxs())
833 new_ctxs
= krealloc(dbgfs_ctxs
, sizeof(*dbgfs_ctxs
) *
834 (dbgfs_nr_ctxs
+ 1), GFP_KERNEL
);
837 dbgfs_ctxs
= new_ctxs
;
839 new_dirs
= krealloc(dbgfs_dirs
, sizeof(*dbgfs_dirs
) *
840 (dbgfs_nr_ctxs
+ 1), GFP_KERNEL
);
843 dbgfs_dirs
= new_dirs
;
845 root
= dbgfs_dirs
[0];
849 new_dir
= debugfs_create_dir(name
, root
);
850 /* Below check is required for a potential duplicated name case */
852 return PTR_ERR(new_dir
);
853 dbgfs_dirs
[dbgfs_nr_ctxs
] = new_dir
;
855 new_ctx
= dbgfs_new_ctx();
857 debugfs_remove(new_dir
);
858 dbgfs_dirs
[dbgfs_nr_ctxs
] = NULL
;
862 dbgfs_ctxs
[dbgfs_nr_ctxs
] = new_ctx
;
863 dbgfs_fill_ctx_dir(dbgfs_dirs
[dbgfs_nr_ctxs
],
864 dbgfs_ctxs
[dbgfs_nr_ctxs
]);
870 static ssize_t
dbgfs_mk_context_write(struct file
*file
,
871 const char __user
*buf
, size_t count
, loff_t
*ppos
)
877 kbuf
= user_input_str(buf
, count
, ppos
);
879 return PTR_ERR(kbuf
);
880 ctx_name
= kmalloc(count
+ 1, GFP_KERNEL
);
886 /* Trim white space */
887 if (sscanf(kbuf
, "%s", ctx_name
) != 1) {
892 mutex_lock(&damon_dbgfs_lock
);
893 ret
= dbgfs_mk_context(ctx_name
);
896 mutex_unlock(&damon_dbgfs_lock
);
905 * Remove a context of @name and its debugfs directory.
907 * This function should be called while holding damon_dbgfs_lock.
909 * Return 0 on success, negative error code otherwise.
911 static int dbgfs_rm_context(char *name
)
913 struct dentry
*root
, *dir
, **new_dirs
;
915 struct damon_ctx
**new_ctxs
;
919 if (damon_nr_running_ctxs())
922 root
= dbgfs_dirs
[0];
926 dir
= debugfs_lookup(name
, root
);
930 inode
= d_inode(dir
);
931 if (!S_ISDIR(inode
->i_mode
)) {
936 new_dirs
= kmalloc_array(dbgfs_nr_ctxs
- 1, sizeof(*dbgfs_dirs
),
943 new_ctxs
= kmalloc_array(dbgfs_nr_ctxs
- 1, sizeof(*dbgfs_ctxs
),
950 for (i
= 0, j
= 0; i
< dbgfs_nr_ctxs
; i
++) {
951 if (dbgfs_dirs
[i
] == dir
) {
952 debugfs_remove(dbgfs_dirs
[i
]);
953 dbgfs_destroy_ctx(dbgfs_ctxs
[i
]);
956 new_dirs
[j
] = dbgfs_dirs
[i
];
957 new_ctxs
[j
++] = dbgfs_ctxs
[i
];
963 dbgfs_dirs
= new_dirs
;
964 dbgfs_ctxs
= new_ctxs
;
976 static ssize_t
dbgfs_rm_context_write(struct file
*file
,
977 const char __user
*buf
, size_t count
, loff_t
*ppos
)
983 kbuf
= user_input_str(buf
, count
, ppos
);
985 return PTR_ERR(kbuf
);
986 ctx_name
= kmalloc(count
+ 1, GFP_KERNEL
);
992 /* Trim white space */
993 if (sscanf(kbuf
, "%s", ctx_name
) != 1) {
998 mutex_lock(&damon_dbgfs_lock
);
999 ret
= dbgfs_rm_context(ctx_name
);
1002 mutex_unlock(&damon_dbgfs_lock
);
1010 static ssize_t
dbgfs_monitor_on_read(struct file
*file
,
1011 char __user
*buf
, size_t count
, loff_t
*ppos
)
1013 char monitor_on_buf
[5];
1014 bool monitor_on
= damon_nr_running_ctxs() != 0;
1017 len
= scnprintf(monitor_on_buf
, 5, monitor_on
? "on\n" : "off\n");
1019 return simple_read_from_buffer(buf
, count
, ppos
, monitor_on_buf
, len
);
1022 static ssize_t
dbgfs_monitor_on_write(struct file
*file
,
1023 const char __user
*buf
, size_t count
, loff_t
*ppos
)
1028 kbuf
= user_input_str(buf
, count
, ppos
);
1030 return PTR_ERR(kbuf
);
1032 /* Remove white space */
1033 if (sscanf(kbuf
, "%s", kbuf
) != 1) {
1038 mutex_lock(&damon_dbgfs_lock
);
1039 if (!strncmp(kbuf
, "on", count
)) {
1042 for (i
= 0; i
< dbgfs_nr_ctxs
; i
++) {
1043 if (damon_targets_empty(dbgfs_ctxs
[i
])) {
1045 mutex_unlock(&damon_dbgfs_lock
);
1049 ret
= damon_start(dbgfs_ctxs
, dbgfs_nr_ctxs
, true);
1050 } else if (!strncmp(kbuf
, "off", count
)) {
1051 ret
= damon_stop(dbgfs_ctxs
, dbgfs_nr_ctxs
);
1055 mutex_unlock(&damon_dbgfs_lock
);
1063 static int damon_dbgfs_static_file_open(struct inode
*inode
, struct file
*file
)
1065 damon_dbgfs_warn_deprecation();
1066 return nonseekable_open(inode
, file
);
1069 static const struct file_operations deprecated_fops
= {
1070 .read
= damon_dbgfs_deprecated_read
,
1073 static const struct file_operations mk_contexts_fops
= {
1074 .open
= damon_dbgfs_static_file_open
,
1075 .write
= dbgfs_mk_context_write
,
1078 static const struct file_operations rm_contexts_fops
= {
1079 .open
= damon_dbgfs_static_file_open
,
1080 .write
= dbgfs_rm_context_write
,
1083 static const struct file_operations monitor_on_fops
= {
1084 .open
= damon_dbgfs_static_file_open
,
1085 .read
= dbgfs_monitor_on_read
,
1086 .write
= dbgfs_monitor_on_write
,
1089 static int __init
__damon_dbgfs_init(void)
1091 struct dentry
*dbgfs_root
;
1092 const char * const file_names
[] = {"mk_contexts", "rm_contexts",
1093 "monitor_on_DEPRECATED", "DEPRECATED"};
1094 const struct file_operations
*fops
[] = {&mk_contexts_fops
,
1095 &rm_contexts_fops
, &monitor_on_fops
, &deprecated_fops
};
1098 dbgfs_root
= debugfs_create_dir("damon", NULL
);
1100 for (i
= 0; i
< ARRAY_SIZE(file_names
); i
++)
1101 debugfs_create_file(file_names
[i
], 0600, dbgfs_root
, NULL
,
1103 dbgfs_fill_ctx_dir(dbgfs_root
, dbgfs_ctxs
[0]);
1105 dbgfs_dirs
= kmalloc(sizeof(dbgfs_root
), GFP_KERNEL
);
1107 debugfs_remove(dbgfs_root
);
1110 dbgfs_dirs
[0] = dbgfs_root
;
1116 * Functions for the initialization
1119 static int __init
damon_dbgfs_init(void)
1123 mutex_lock(&damon_dbgfs_lock
);
1124 dbgfs_ctxs
= kmalloc(sizeof(*dbgfs_ctxs
), GFP_KERNEL
);
1127 dbgfs_ctxs
[0] = dbgfs_new_ctx();
1128 if (!dbgfs_ctxs
[0]) {
1134 rc
= __damon_dbgfs_init();
1136 kfree(dbgfs_ctxs
[0]);
1138 pr_err("%s: dbgfs init failed\n", __func__
);
1142 mutex_unlock(&damon_dbgfs_lock
);
1146 module_init(damon_dbgfs_init
);
1148 #include "tests/dbgfs-kunit.h"