1 // SPDX-License-Identifier: GPL-2.0
3 * DAMON Debugfs Interface
5 * Author: SeongJae Park <sjpark@amazon.de>
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 static struct damon_ctx **dbgfs_ctxs;
19 static int dbgfs_nr_ctxs;
20 static struct dentry **dbgfs_dirs;
21 static DEFINE_MUTEX(damon_dbgfs_lock);
24 * Returns non-empty string on success, negative error code otherwise.
26 static char *user_input_str(const char __user *buf, size_t count, loff_t *ppos)
31 /* We do not accept continuous write */
33 return ERR_PTR(-EINVAL);
35 kbuf = kmalloc(count + 1, GFP_KERNEL | __GFP_NOWARN);
37 return ERR_PTR(-ENOMEM);
39 ret = simple_write_to_buffer(kbuf, count + 1, ppos, buf, count);
49 static ssize_t dbgfs_attrs_read(struct file *file,
50 char __user *buf, size_t count, loff_t *ppos)
52 struct damon_ctx *ctx = file->private_data;
56 mutex_lock(&ctx->kdamond_lock);
57 ret = scnprintf(kbuf, ARRAY_SIZE(kbuf), "%lu %lu %lu %lu %lu\n",
58 ctx->attrs.sample_interval, ctx->attrs.aggr_interval,
59 ctx->attrs.ops_update_interval,
60 ctx->attrs.min_nr_regions, ctx->attrs.max_nr_regions);
61 mutex_unlock(&ctx->kdamond_lock);
63 return simple_read_from_buffer(buf, count, ppos, kbuf, ret);
66 static ssize_t dbgfs_attrs_write(struct file *file,
67 const char __user *buf, size_t count, loff_t *ppos)
69 struct damon_ctx *ctx = file->private_data;
70 struct damon_attrs attrs;
74 kbuf = user_input_str(buf, count, ppos);
78 if (sscanf(kbuf, "%lu %lu %lu %lu %lu",
79 &attrs.sample_interval, &attrs.aggr_interval,
80 &attrs.ops_update_interval,
81 &attrs.min_nr_regions,
82 &attrs.max_nr_regions) != 5) {
87 mutex_lock(&ctx->kdamond_lock);
93 ret = damon_set_attrs(ctx, &attrs);
97 mutex_unlock(&ctx->kdamond_lock);
104 * Return corresponding dbgfs' scheme action value (int) for the given
105 * damos_action if the given damos_action value is valid and supported by
106 * dbgfs, negative error code otherwise.
108 static int damos_action_to_dbgfs_scheme_action(enum damos_action action)
119 case DAMOS_NOHUGEPAGE:
128 static ssize_t sprint_schemes(struct damon_ctx *c, char *buf, ssize_t len)
134 damon_for_each_scheme(s, c) {
135 rc = scnprintf(&buf[written], len - written,
136 "%lu %lu %u %u %u %u %d %lu %lu %lu %u %u %u %d %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
137 s->pattern.min_sz_region,
138 s->pattern.max_sz_region,
139 s->pattern.min_nr_accesses,
140 s->pattern.max_nr_accesses,
141 s->pattern.min_age_region,
142 s->pattern.max_age_region,
143 damos_action_to_dbgfs_scheme_action(s->action),
144 s->quota.ms, s->quota.sz,
145 s->quota.reset_interval,
147 s->quota.weight_nr_accesses,
149 s->wmarks.metric, s->wmarks.interval,
150 s->wmarks.high, s->wmarks.mid, s->wmarks.low,
151 s->stat.nr_tried, s->stat.sz_tried,
152 s->stat.nr_applied, s->stat.sz_applied,
162 static ssize_t dbgfs_schemes_read(struct file *file, char __user *buf,
163 size_t count, loff_t *ppos)
165 struct damon_ctx *ctx = file->private_data;
169 kbuf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN);
173 mutex_lock(&ctx->kdamond_lock);
174 len = sprint_schemes(ctx, kbuf, count);
175 mutex_unlock(&ctx->kdamond_lock);
178 len = simple_read_from_buffer(buf, count, ppos, kbuf, len);
185 static void free_schemes_arr(struct damos **schemes, ssize_t nr_schemes)
189 for (i = 0; i < nr_schemes; i++)
195 * Return corresponding damos_action for the given dbgfs input for a scheme
196 * action if the input is valid, negative error code otherwise.
198 static enum damos_action dbgfs_scheme_action_to_damos_action(int dbgfs_action)
200 switch (dbgfs_action) {
202 return DAMOS_WILLNEED;
206 return DAMOS_PAGEOUT;
208 return DAMOS_HUGEPAGE;
210 return DAMOS_NOHUGEPAGE;
219 * Converts a string into an array of struct damos pointers
221 * Returns an array of struct damos pointers that converted if the conversion
222 * success, or NULL otherwise.
224 static struct damos **str_to_schemes(const char *str, ssize_t len,
227 struct damos *scheme, **schemes;
228 const int max_nr_schemes = 256;
229 int pos = 0, parsed, ret;
230 unsigned int action_input;
231 enum damos_action action;
233 schemes = kmalloc_array(max_nr_schemes, sizeof(scheme),
239 while (pos < len && *nr_schemes < max_nr_schemes) {
240 struct damos_access_pattern pattern = {};
241 struct damos_quota quota = {};
242 struct damos_watermarks wmarks;
244 ret = sscanf(&str[pos],
245 "%lu %lu %u %u %u %u %u %lu %lu %lu %u %u %u %u %lu %lu %lu %lu%n",
246 &pattern.min_sz_region, &pattern.max_sz_region,
247 &pattern.min_nr_accesses,
248 &pattern.max_nr_accesses,
249 &pattern.min_age_region,
250 &pattern.max_age_region,
251 &action_input, "a.ms,
252 "a.sz, "a.reset_interval,
253 "a.weight_sz, "a.weight_nr_accesses,
254 "a.weight_age, &wmarks.metric,
255 &wmarks.interval, &wmarks.high, &wmarks.mid,
256 &wmarks.low, &parsed);
259 action = dbgfs_scheme_action_to_damos_action(action_input);
263 if (pattern.min_sz_region > pattern.max_sz_region ||
264 pattern.min_nr_accesses > pattern.max_nr_accesses ||
265 pattern.min_age_region > pattern.max_age_region)
268 if (wmarks.high < wmarks.mid || wmarks.high < wmarks.low ||
269 wmarks.mid < wmarks.low)
273 scheme = damon_new_scheme(&pattern, action, "a, &wmarks);
277 schemes[*nr_schemes] = scheme;
282 free_schemes_arr(schemes, *nr_schemes);
286 static ssize_t dbgfs_schemes_write(struct file *file, const char __user *buf,
287 size_t count, loff_t *ppos)
289 struct damon_ctx *ctx = file->private_data;
291 struct damos **schemes;
292 ssize_t nr_schemes = 0, ret;
294 kbuf = user_input_str(buf, count, ppos);
296 return PTR_ERR(kbuf);
298 schemes = str_to_schemes(kbuf, count, &nr_schemes);
304 mutex_lock(&ctx->kdamond_lock);
310 damon_set_schemes(ctx, schemes, nr_schemes);
315 mutex_unlock(&ctx->kdamond_lock);
316 free_schemes_arr(schemes, nr_schemes);
322 static ssize_t sprint_target_ids(struct damon_ctx *ctx, char *buf, ssize_t len)
324 struct damon_target *t;
329 damon_for_each_target(t, ctx) {
330 if (damon_target_has_pid(ctx))
331 /* Show pid numbers to debugfs users */
332 id = pid_vnr(t->pid);
334 /* Show 42 for physical address space, just for fun */
337 rc = scnprintf(&buf[written], len - written, "%d ", id);
344 written += scnprintf(&buf[written], len - written, "\n");
348 static ssize_t dbgfs_target_ids_read(struct file *file,
349 char __user *buf, size_t count, loff_t *ppos)
351 struct damon_ctx *ctx = file->private_data;
355 mutex_lock(&ctx->kdamond_lock);
356 len = sprint_target_ids(ctx, ids_buf, 320);
357 mutex_unlock(&ctx->kdamond_lock);
361 return simple_read_from_buffer(buf, count, ppos, ids_buf, len);
365 * Converts a string into an integers array
367 * Returns an array of integers array if the conversion success, or NULL
370 static int *str_to_ints(const char *str, ssize_t len, ssize_t *nr_ints)
373 const int max_nr_ints = 32;
375 int pos = 0, parsed, ret;
378 array = kmalloc_array(max_nr_ints, sizeof(*array), GFP_KERNEL);
381 while (*nr_ints < max_nr_ints && pos < len) {
382 ret = sscanf(&str[pos], "%d%n", &nr, &parsed);
386 array[*nr_ints] = nr;
393 static void dbgfs_put_pids(struct pid **pids, int nr_pids)
397 for (i = 0; i < nr_pids; i++)
402 * Converts a string into an struct pid pointers array
404 * Returns an array of struct pid pointers if the conversion success, or NULL
407 static struct pid **str_to_pids(const char *str, ssize_t len, ssize_t *nr_pids)
415 ints = str_to_ints(str, len, &nr_ints);
419 pids = kmalloc_array(nr_ints, sizeof(*pids), GFP_KERNEL);
423 for (; *nr_pids < nr_ints; (*nr_pids)++) {
424 pids[*nr_pids] = find_get_pid(ints[*nr_pids]);
425 if (!pids[*nr_pids]) {
426 dbgfs_put_pids(pids, *nr_pids);
439 * dbgfs_set_targets() - Set monitoring targets.
440 * @ctx: monitoring context
441 * @nr_targets: number of targets
442 * @pids: array of target pids (size is same to @nr_targets)
444 * This function should not be called while the kdamond is running. @pids is
445 * ignored if the context is not configured to have pid in each target. On
446 * failure, reference counts of all pids in @pids are decremented.
448 * Return: 0 on success, negative error code otherwise.
450 static int dbgfs_set_targets(struct damon_ctx *ctx, ssize_t nr_targets,
454 struct damon_target *t, *next;
456 damon_for_each_target_safe(t, next, ctx) {
457 if (damon_target_has_pid(ctx))
459 damon_destroy_target(t);
462 for (i = 0; i < nr_targets; i++) {
463 t = damon_new_target();
465 damon_for_each_target_safe(t, next, ctx)
466 damon_destroy_target(t);
467 if (damon_target_has_pid(ctx))
468 dbgfs_put_pids(pids, nr_targets);
471 if (damon_target_has_pid(ctx))
473 damon_add_target(ctx, t);
479 static ssize_t dbgfs_target_ids_write(struct file *file,
480 const char __user *buf, size_t count, loff_t *ppos)
482 struct damon_ctx *ctx = file->private_data;
483 bool id_is_pid = true;
485 struct pid **target_pids = NULL;
489 kbuf = user_input_str(buf, count, ppos);
491 return PTR_ERR(kbuf);
493 if (!strncmp(kbuf, "paddr\n", count)) {
499 target_pids = str_to_pids(kbuf, count, &nr_targets);
506 mutex_lock(&ctx->kdamond_lock);
509 dbgfs_put_pids(target_pids, nr_targets);
514 /* remove previously set targets */
515 dbgfs_set_targets(ctx, 0, NULL);
521 /* Configure the context for the address space type */
523 ret = damon_select_ops(ctx, DAMON_OPS_VADDR);
525 ret = damon_select_ops(ctx, DAMON_OPS_PADDR);
529 ret = dbgfs_set_targets(ctx, nr_targets, target_pids);
534 mutex_unlock(&ctx->kdamond_lock);
541 static ssize_t sprint_init_regions(struct damon_ctx *c, char *buf, ssize_t len)
543 struct damon_target *t;
544 struct damon_region *r;
549 damon_for_each_target(t, c) {
550 damon_for_each_region(r, t) {
551 rc = scnprintf(&buf[written], len - written,
553 target_idx, r->ar.start, r->ar.end);
563 static ssize_t dbgfs_init_regions_read(struct file *file, char __user *buf,
564 size_t count, loff_t *ppos)
566 struct damon_ctx *ctx = file->private_data;
570 kbuf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN);
574 mutex_lock(&ctx->kdamond_lock);
576 mutex_unlock(&ctx->kdamond_lock);
581 len = sprint_init_regions(ctx, kbuf, count);
582 mutex_unlock(&ctx->kdamond_lock);
585 len = simple_read_from_buffer(buf, count, ppos, kbuf, len);
592 static int add_init_region(struct damon_ctx *c, int target_idx,
593 struct damon_addr_range *ar)
595 struct damon_target *t;
596 struct damon_region *r, *prev;
597 unsigned long idx = 0;
600 if (ar->start >= ar->end)
603 damon_for_each_target(t, c) {
604 if (idx++ == target_idx) {
605 r = damon_new_region(ar->start, ar->end);
608 damon_add_region(r, t);
609 if (damon_nr_regions(t) > 1) {
610 prev = damon_prev_region(r);
611 if (prev->ar.end > r->ar.start) {
612 damon_destroy_region(r, t);
622 static int set_init_regions(struct damon_ctx *c, const char *str, ssize_t len)
624 struct damon_target *t;
625 struct damon_region *r, *next;
626 int pos = 0, parsed, ret;
628 struct damon_addr_range ar;
631 damon_for_each_target(t, c) {
632 damon_for_each_region_safe(r, next, t)
633 damon_destroy_region(r, t);
637 ret = sscanf(&str[pos], "%d %lu %lu%n",
638 &target_idx, &ar.start, &ar.end, &parsed);
641 err = add_init_region(c, target_idx, &ar);
650 damon_for_each_target(t, c) {
651 damon_for_each_region_safe(r, next, t)
652 damon_destroy_region(r, t);
657 static ssize_t dbgfs_init_regions_write(struct file *file,
658 const char __user *buf, size_t count,
661 struct damon_ctx *ctx = file->private_data;
666 kbuf = user_input_str(buf, count, ppos);
668 return PTR_ERR(kbuf);
670 mutex_lock(&ctx->kdamond_lock);
676 err = set_init_regions(ctx, kbuf, ret);
681 mutex_unlock(&ctx->kdamond_lock);
686 static ssize_t dbgfs_kdamond_pid_read(struct file *file,
687 char __user *buf, size_t count, loff_t *ppos)
689 struct damon_ctx *ctx = file->private_data;
693 kbuf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN);
697 mutex_lock(&ctx->kdamond_lock);
699 len = scnprintf(kbuf, count, "%d\n", ctx->kdamond->pid);
701 len = scnprintf(kbuf, count, "none\n");
702 mutex_unlock(&ctx->kdamond_lock);
705 len = simple_read_from_buffer(buf, count, ppos, kbuf, len);
712 static int damon_dbgfs_open(struct inode *inode, struct file *file)
714 file->private_data = inode->i_private;
716 return nonseekable_open(inode, file);
719 static const struct file_operations attrs_fops = {
720 .open = damon_dbgfs_open,
721 .read = dbgfs_attrs_read,
722 .write = dbgfs_attrs_write,
725 static const struct file_operations schemes_fops = {
726 .open = damon_dbgfs_open,
727 .read = dbgfs_schemes_read,
728 .write = dbgfs_schemes_write,
731 static const struct file_operations target_ids_fops = {
732 .open = damon_dbgfs_open,
733 .read = dbgfs_target_ids_read,
734 .write = dbgfs_target_ids_write,
737 static const struct file_operations init_regions_fops = {
738 .open = damon_dbgfs_open,
739 .read = dbgfs_init_regions_read,
740 .write = dbgfs_init_regions_write,
743 static const struct file_operations kdamond_pid_fops = {
744 .open = damon_dbgfs_open,
745 .read = dbgfs_kdamond_pid_read,
748 static void dbgfs_fill_ctx_dir(struct dentry *dir, struct damon_ctx *ctx)
750 const char * const file_names[] = {"attrs", "schemes", "target_ids",
751 "init_regions", "kdamond_pid"};
752 const struct file_operations *fops[] = {&attrs_fops, &schemes_fops,
753 &target_ids_fops, &init_regions_fops, &kdamond_pid_fops};
756 for (i = 0; i < ARRAY_SIZE(file_names); i++)
757 debugfs_create_file(file_names[i], 0600, dir, ctx, fops[i]);
760 static void dbgfs_before_terminate(struct damon_ctx *ctx)
762 struct damon_target *t, *next;
764 if (!damon_target_has_pid(ctx))
767 mutex_lock(&ctx->kdamond_lock);
768 damon_for_each_target_safe(t, next, ctx) {
770 damon_destroy_target(t);
772 mutex_unlock(&ctx->kdamond_lock);
775 static struct damon_ctx *dbgfs_new_ctx(void)
777 struct damon_ctx *ctx;
779 ctx = damon_new_ctx();
783 if (damon_select_ops(ctx, DAMON_OPS_VADDR) &&
784 damon_select_ops(ctx, DAMON_OPS_PADDR)) {
785 damon_destroy_ctx(ctx);
788 ctx->callback.before_terminate = dbgfs_before_terminate;
792 static void dbgfs_destroy_ctx(struct damon_ctx *ctx)
794 damon_destroy_ctx(ctx);
798 * Make a context of @name and create a debugfs directory for it.
800 * This function should be called while holding damon_dbgfs_lock.
802 * Returns 0 on success, negative error code otherwise.
804 static int dbgfs_mk_context(char *name)
806 struct dentry *root, **new_dirs, *new_dir;
807 struct damon_ctx **new_ctxs, *new_ctx;
809 if (damon_nr_running_ctxs())
812 new_ctxs = krealloc(dbgfs_ctxs, sizeof(*dbgfs_ctxs) *
813 (dbgfs_nr_ctxs + 1), GFP_KERNEL);
816 dbgfs_ctxs = new_ctxs;
818 new_dirs = krealloc(dbgfs_dirs, sizeof(*dbgfs_dirs) *
819 (dbgfs_nr_ctxs + 1), GFP_KERNEL);
822 dbgfs_dirs = new_dirs;
824 root = dbgfs_dirs[0];
828 new_dir = debugfs_create_dir(name, root);
829 /* Below check is required for a potential duplicated name case */
831 return PTR_ERR(new_dir);
832 dbgfs_dirs[dbgfs_nr_ctxs] = new_dir;
834 new_ctx = dbgfs_new_ctx();
836 debugfs_remove(new_dir);
837 dbgfs_dirs[dbgfs_nr_ctxs] = NULL;
841 dbgfs_ctxs[dbgfs_nr_ctxs] = new_ctx;
842 dbgfs_fill_ctx_dir(dbgfs_dirs[dbgfs_nr_ctxs],
843 dbgfs_ctxs[dbgfs_nr_ctxs]);
849 static ssize_t dbgfs_mk_context_write(struct file *file,
850 const char __user *buf, size_t count, loff_t *ppos)
856 kbuf = user_input_str(buf, count, ppos);
858 return PTR_ERR(kbuf);
859 ctx_name = kmalloc(count + 1, GFP_KERNEL);
865 /* Trim white space */
866 if (sscanf(kbuf, "%s", ctx_name) != 1) {
871 mutex_lock(&damon_dbgfs_lock);
872 ret = dbgfs_mk_context(ctx_name);
875 mutex_unlock(&damon_dbgfs_lock);
884 * Remove a context of @name and its debugfs directory.
886 * This function should be called while holding damon_dbgfs_lock.
888 * Return 0 on success, negative error code otherwise.
890 static int dbgfs_rm_context(char *name)
892 struct dentry *root, *dir, **new_dirs;
894 struct damon_ctx **new_ctxs;
898 if (damon_nr_running_ctxs())
901 root = dbgfs_dirs[0];
905 dir = debugfs_lookup(name, root);
909 inode = d_inode(dir);
910 if (!S_ISDIR(inode->i_mode)) {
915 new_dirs = kmalloc_array(dbgfs_nr_ctxs - 1, sizeof(*dbgfs_dirs),
922 new_ctxs = kmalloc_array(dbgfs_nr_ctxs - 1, sizeof(*dbgfs_ctxs),
929 for (i = 0, j = 0; i < dbgfs_nr_ctxs; i++) {
930 if (dbgfs_dirs[i] == dir) {
931 debugfs_remove(dbgfs_dirs[i]);
932 dbgfs_destroy_ctx(dbgfs_ctxs[i]);
935 new_dirs[j] = dbgfs_dirs[i];
936 new_ctxs[j++] = dbgfs_ctxs[i];
942 dbgfs_dirs = new_dirs;
943 dbgfs_ctxs = new_ctxs;
955 static ssize_t dbgfs_rm_context_write(struct file *file,
956 const char __user *buf, size_t count, loff_t *ppos)
962 kbuf = user_input_str(buf, count, ppos);
964 return PTR_ERR(kbuf);
965 ctx_name = kmalloc(count + 1, GFP_KERNEL);
971 /* Trim white space */
972 if (sscanf(kbuf, "%s", ctx_name) != 1) {
977 mutex_lock(&damon_dbgfs_lock);
978 ret = dbgfs_rm_context(ctx_name);
981 mutex_unlock(&damon_dbgfs_lock);
989 static ssize_t dbgfs_monitor_on_read(struct file *file,
990 char __user *buf, size_t count, loff_t *ppos)
992 char monitor_on_buf[5];
993 bool monitor_on = damon_nr_running_ctxs() != 0;
996 len = scnprintf(monitor_on_buf, 5, monitor_on ? "on\n" : "off\n");
998 return simple_read_from_buffer(buf, count, ppos, monitor_on_buf, len);
1001 static ssize_t dbgfs_monitor_on_write(struct file *file,
1002 const char __user *buf, size_t count, loff_t *ppos)
1007 kbuf = user_input_str(buf, count, ppos);
1009 return PTR_ERR(kbuf);
1011 /* Remove white space */
1012 if (sscanf(kbuf, "%s", kbuf) != 1) {
1017 mutex_lock(&damon_dbgfs_lock);
1018 if (!strncmp(kbuf, "on", count)) {
1021 for (i = 0; i < dbgfs_nr_ctxs; i++) {
1022 if (damon_targets_empty(dbgfs_ctxs[i])) {
1024 mutex_unlock(&damon_dbgfs_lock);
1028 ret = damon_start(dbgfs_ctxs, dbgfs_nr_ctxs, true);
1029 } else if (!strncmp(kbuf, "off", count)) {
1030 ret = damon_stop(dbgfs_ctxs, dbgfs_nr_ctxs);
1034 mutex_unlock(&damon_dbgfs_lock);
1042 static const struct file_operations mk_contexts_fops = {
1043 .write = dbgfs_mk_context_write,
1046 static const struct file_operations rm_contexts_fops = {
1047 .write = dbgfs_rm_context_write,
1050 static const struct file_operations monitor_on_fops = {
1051 .read = dbgfs_monitor_on_read,
1052 .write = dbgfs_monitor_on_write,
1055 static int __init __damon_dbgfs_init(void)
1057 struct dentry *dbgfs_root;
1058 const char * const file_names[] = {"mk_contexts", "rm_contexts",
1060 const struct file_operations *fops[] = {&mk_contexts_fops,
1061 &rm_contexts_fops, &monitor_on_fops};
1064 dbgfs_root = debugfs_create_dir("damon", NULL);
1066 for (i = 0; i < ARRAY_SIZE(file_names); i++)
1067 debugfs_create_file(file_names[i], 0600, dbgfs_root, NULL,
1069 dbgfs_fill_ctx_dir(dbgfs_root, dbgfs_ctxs[0]);
1071 dbgfs_dirs = kmalloc(sizeof(dbgfs_root), GFP_KERNEL);
1073 debugfs_remove(dbgfs_root);
1076 dbgfs_dirs[0] = dbgfs_root;
1082 * Functions for the initialization
1085 static int __init damon_dbgfs_init(void)
1089 mutex_lock(&damon_dbgfs_lock);
1090 dbgfs_ctxs = kmalloc(sizeof(*dbgfs_ctxs), GFP_KERNEL);
1093 dbgfs_ctxs[0] = dbgfs_new_ctx();
1094 if (!dbgfs_ctxs[0]) {
1100 rc = __damon_dbgfs_init();
1102 kfree(dbgfs_ctxs[0]);
1104 pr_err("%s: dbgfs init failed\n", __func__);
1108 mutex_unlock(&damon_dbgfs_lock);
1112 module_init(damon_dbgfs_init);
1114 #include "dbgfs-test.h"