1*4bc05954SSeongJae Park // SPDX-License-Identifier: GPL-2.0 2*4bc05954SSeongJae Park /* 3*4bc05954SSeongJae Park * DAMON Debugfs Interface 4*4bc05954SSeongJae Park * 5*4bc05954SSeongJae Park * Author: SeongJae Park <sjpark@amazon.de> 6*4bc05954SSeongJae Park */ 7*4bc05954SSeongJae Park 8*4bc05954SSeongJae Park #define pr_fmt(fmt) "damon-dbgfs: " fmt 9*4bc05954SSeongJae Park 10*4bc05954SSeongJae Park #include <linux/damon.h> 11*4bc05954SSeongJae Park #include <linux/debugfs.h> 12*4bc05954SSeongJae Park #include <linux/file.h> 13*4bc05954SSeongJae Park #include <linux/mm.h> 14*4bc05954SSeongJae Park #include <linux/module.h> 15*4bc05954SSeongJae Park #include <linux/page_idle.h> 16*4bc05954SSeongJae Park #include <linux/slab.h> 17*4bc05954SSeongJae Park 18*4bc05954SSeongJae Park static struct damon_ctx **dbgfs_ctxs; 19*4bc05954SSeongJae Park static int dbgfs_nr_ctxs; 20*4bc05954SSeongJae Park static struct dentry **dbgfs_dirs; 21*4bc05954SSeongJae Park 22*4bc05954SSeongJae Park /* 23*4bc05954SSeongJae Park * Returns non-empty string on success, negative error code otherwise. 24*4bc05954SSeongJae Park */ 25*4bc05954SSeongJae Park static char *user_input_str(const char __user *buf, size_t count, loff_t *ppos) 26*4bc05954SSeongJae Park { 27*4bc05954SSeongJae Park char *kbuf; 28*4bc05954SSeongJae Park ssize_t ret; 29*4bc05954SSeongJae Park 30*4bc05954SSeongJae Park /* We do not accept continuous write */ 31*4bc05954SSeongJae Park if (*ppos) 32*4bc05954SSeongJae Park return ERR_PTR(-EINVAL); 33*4bc05954SSeongJae Park 34*4bc05954SSeongJae Park kbuf = kmalloc(count + 1, GFP_KERNEL); 35*4bc05954SSeongJae Park if (!kbuf) 36*4bc05954SSeongJae Park return ERR_PTR(-ENOMEM); 37*4bc05954SSeongJae Park 38*4bc05954SSeongJae Park ret = simple_write_to_buffer(kbuf, count + 1, ppos, buf, count); 39*4bc05954SSeongJae Park if (ret != count) { 40*4bc05954SSeongJae Park kfree(kbuf); 41*4bc05954SSeongJae Park return ERR_PTR(-EIO); 42*4bc05954SSeongJae Park } 43*4bc05954SSeongJae Park kbuf[ret] = '\0'; 44*4bc05954SSeongJae Park 45*4bc05954SSeongJae Park return kbuf; 46*4bc05954SSeongJae Park } 47*4bc05954SSeongJae Park 48*4bc05954SSeongJae Park static ssize_t dbgfs_attrs_read(struct file *file, 49*4bc05954SSeongJae Park char __user *buf, size_t count, loff_t *ppos) 50*4bc05954SSeongJae Park { 51*4bc05954SSeongJae Park struct damon_ctx *ctx = file->private_data; 52*4bc05954SSeongJae Park char kbuf[128]; 53*4bc05954SSeongJae Park int ret; 54*4bc05954SSeongJae Park 55*4bc05954SSeongJae Park mutex_lock(&ctx->kdamond_lock); 56*4bc05954SSeongJae Park ret = scnprintf(kbuf, ARRAY_SIZE(kbuf), "%lu %lu %lu %lu %lu\n", 57*4bc05954SSeongJae Park ctx->sample_interval, ctx->aggr_interval, 58*4bc05954SSeongJae Park ctx->primitive_update_interval, ctx->min_nr_regions, 59*4bc05954SSeongJae Park ctx->max_nr_regions); 60*4bc05954SSeongJae Park mutex_unlock(&ctx->kdamond_lock); 61*4bc05954SSeongJae Park 62*4bc05954SSeongJae Park return simple_read_from_buffer(buf, count, ppos, kbuf, ret); 63*4bc05954SSeongJae Park } 64*4bc05954SSeongJae Park 65*4bc05954SSeongJae Park static ssize_t dbgfs_attrs_write(struct file *file, 66*4bc05954SSeongJae Park const char __user *buf, size_t count, loff_t *ppos) 67*4bc05954SSeongJae Park { 68*4bc05954SSeongJae Park struct damon_ctx *ctx = file->private_data; 69*4bc05954SSeongJae Park unsigned long s, a, r, minr, maxr; 70*4bc05954SSeongJae Park char *kbuf; 71*4bc05954SSeongJae Park ssize_t ret = count; 72*4bc05954SSeongJae Park int err; 73*4bc05954SSeongJae Park 74*4bc05954SSeongJae Park kbuf = user_input_str(buf, count, ppos); 75*4bc05954SSeongJae Park if (IS_ERR(kbuf)) 76*4bc05954SSeongJae Park return PTR_ERR(kbuf); 77*4bc05954SSeongJae Park 78*4bc05954SSeongJae Park if (sscanf(kbuf, "%lu %lu %lu %lu %lu", 79*4bc05954SSeongJae Park &s, &a, &r, &minr, &maxr) != 5) { 80*4bc05954SSeongJae Park ret = -EINVAL; 81*4bc05954SSeongJae Park goto out; 82*4bc05954SSeongJae Park } 83*4bc05954SSeongJae Park 84*4bc05954SSeongJae Park mutex_lock(&ctx->kdamond_lock); 85*4bc05954SSeongJae Park if (ctx->kdamond) { 86*4bc05954SSeongJae Park ret = -EBUSY; 87*4bc05954SSeongJae Park goto unlock_out; 88*4bc05954SSeongJae Park } 89*4bc05954SSeongJae Park 90*4bc05954SSeongJae Park err = damon_set_attrs(ctx, s, a, r, minr, maxr); 91*4bc05954SSeongJae Park if (err) 92*4bc05954SSeongJae Park ret = err; 93*4bc05954SSeongJae Park unlock_out: 94*4bc05954SSeongJae Park mutex_unlock(&ctx->kdamond_lock); 95*4bc05954SSeongJae Park out: 96*4bc05954SSeongJae Park kfree(kbuf); 97*4bc05954SSeongJae Park return ret; 98*4bc05954SSeongJae Park } 99*4bc05954SSeongJae Park 100*4bc05954SSeongJae Park static inline bool targetid_is_pid(const struct damon_ctx *ctx) 101*4bc05954SSeongJae Park { 102*4bc05954SSeongJae Park return ctx->primitive.target_valid == damon_va_target_valid; 103*4bc05954SSeongJae Park } 104*4bc05954SSeongJae Park 105*4bc05954SSeongJae Park static ssize_t sprint_target_ids(struct damon_ctx *ctx, char *buf, ssize_t len) 106*4bc05954SSeongJae Park { 107*4bc05954SSeongJae Park struct damon_target *t; 108*4bc05954SSeongJae Park unsigned long id; 109*4bc05954SSeongJae Park int written = 0; 110*4bc05954SSeongJae Park int rc; 111*4bc05954SSeongJae Park 112*4bc05954SSeongJae Park damon_for_each_target(t, ctx) { 113*4bc05954SSeongJae Park id = t->id; 114*4bc05954SSeongJae Park if (targetid_is_pid(ctx)) 115*4bc05954SSeongJae Park /* Show pid numbers to debugfs users */ 116*4bc05954SSeongJae Park id = (unsigned long)pid_vnr((struct pid *)id); 117*4bc05954SSeongJae Park 118*4bc05954SSeongJae Park rc = scnprintf(&buf[written], len - written, "%lu ", id); 119*4bc05954SSeongJae Park if (!rc) 120*4bc05954SSeongJae Park return -ENOMEM; 121*4bc05954SSeongJae Park written += rc; 122*4bc05954SSeongJae Park } 123*4bc05954SSeongJae Park if (written) 124*4bc05954SSeongJae Park written -= 1; 125*4bc05954SSeongJae Park written += scnprintf(&buf[written], len - written, "\n"); 126*4bc05954SSeongJae Park return written; 127*4bc05954SSeongJae Park } 128*4bc05954SSeongJae Park 129*4bc05954SSeongJae Park static ssize_t dbgfs_target_ids_read(struct file *file, 130*4bc05954SSeongJae Park char __user *buf, size_t count, loff_t *ppos) 131*4bc05954SSeongJae Park { 132*4bc05954SSeongJae Park struct damon_ctx *ctx = file->private_data; 133*4bc05954SSeongJae Park ssize_t len; 134*4bc05954SSeongJae Park char ids_buf[320]; 135*4bc05954SSeongJae Park 136*4bc05954SSeongJae Park mutex_lock(&ctx->kdamond_lock); 137*4bc05954SSeongJae Park len = sprint_target_ids(ctx, ids_buf, 320); 138*4bc05954SSeongJae Park mutex_unlock(&ctx->kdamond_lock); 139*4bc05954SSeongJae Park if (len < 0) 140*4bc05954SSeongJae Park return len; 141*4bc05954SSeongJae Park 142*4bc05954SSeongJae Park return simple_read_from_buffer(buf, count, ppos, ids_buf, len); 143*4bc05954SSeongJae Park } 144*4bc05954SSeongJae Park 145*4bc05954SSeongJae Park /* 146*4bc05954SSeongJae Park * Converts a string into an array of unsigned long integers 147*4bc05954SSeongJae Park * 148*4bc05954SSeongJae Park * Returns an array of unsigned long integers if the conversion success, or 149*4bc05954SSeongJae Park * NULL otherwise. 150*4bc05954SSeongJae Park */ 151*4bc05954SSeongJae Park static unsigned long *str_to_target_ids(const char *str, ssize_t len, 152*4bc05954SSeongJae Park ssize_t *nr_ids) 153*4bc05954SSeongJae Park { 154*4bc05954SSeongJae Park unsigned long *ids; 155*4bc05954SSeongJae Park const int max_nr_ids = 32; 156*4bc05954SSeongJae Park unsigned long id; 157*4bc05954SSeongJae Park int pos = 0, parsed, ret; 158*4bc05954SSeongJae Park 159*4bc05954SSeongJae Park *nr_ids = 0; 160*4bc05954SSeongJae Park ids = kmalloc_array(max_nr_ids, sizeof(id), GFP_KERNEL); 161*4bc05954SSeongJae Park if (!ids) 162*4bc05954SSeongJae Park return NULL; 163*4bc05954SSeongJae Park while (*nr_ids < max_nr_ids && pos < len) { 164*4bc05954SSeongJae Park ret = sscanf(&str[pos], "%lu%n", &id, &parsed); 165*4bc05954SSeongJae Park pos += parsed; 166*4bc05954SSeongJae Park if (ret != 1) 167*4bc05954SSeongJae Park break; 168*4bc05954SSeongJae Park ids[*nr_ids] = id; 169*4bc05954SSeongJae Park *nr_ids += 1; 170*4bc05954SSeongJae Park } 171*4bc05954SSeongJae Park 172*4bc05954SSeongJae Park return ids; 173*4bc05954SSeongJae Park } 174*4bc05954SSeongJae Park 175*4bc05954SSeongJae Park static void dbgfs_put_pids(unsigned long *ids, int nr_ids) 176*4bc05954SSeongJae Park { 177*4bc05954SSeongJae Park int i; 178*4bc05954SSeongJae Park 179*4bc05954SSeongJae Park for (i = 0; i < nr_ids; i++) 180*4bc05954SSeongJae Park put_pid((struct pid *)ids[i]); 181*4bc05954SSeongJae Park } 182*4bc05954SSeongJae Park 183*4bc05954SSeongJae Park static ssize_t dbgfs_target_ids_write(struct file *file, 184*4bc05954SSeongJae Park const char __user *buf, size_t count, loff_t *ppos) 185*4bc05954SSeongJae Park { 186*4bc05954SSeongJae Park struct damon_ctx *ctx = file->private_data; 187*4bc05954SSeongJae Park char *kbuf, *nrs; 188*4bc05954SSeongJae Park unsigned long *targets; 189*4bc05954SSeongJae Park ssize_t nr_targets; 190*4bc05954SSeongJae Park ssize_t ret = count; 191*4bc05954SSeongJae Park int i; 192*4bc05954SSeongJae Park int err; 193*4bc05954SSeongJae Park 194*4bc05954SSeongJae Park kbuf = user_input_str(buf, count, ppos); 195*4bc05954SSeongJae Park if (IS_ERR(kbuf)) 196*4bc05954SSeongJae Park return PTR_ERR(kbuf); 197*4bc05954SSeongJae Park 198*4bc05954SSeongJae Park nrs = kbuf; 199*4bc05954SSeongJae Park 200*4bc05954SSeongJae Park targets = str_to_target_ids(nrs, ret, &nr_targets); 201*4bc05954SSeongJae Park if (!targets) { 202*4bc05954SSeongJae Park ret = -ENOMEM; 203*4bc05954SSeongJae Park goto out; 204*4bc05954SSeongJae Park } 205*4bc05954SSeongJae Park 206*4bc05954SSeongJae Park if (targetid_is_pid(ctx)) { 207*4bc05954SSeongJae Park for (i = 0; i < nr_targets; i++) { 208*4bc05954SSeongJae Park targets[i] = (unsigned long)find_get_pid( 209*4bc05954SSeongJae Park (int)targets[i]); 210*4bc05954SSeongJae Park if (!targets[i]) { 211*4bc05954SSeongJae Park dbgfs_put_pids(targets, i); 212*4bc05954SSeongJae Park ret = -EINVAL; 213*4bc05954SSeongJae Park goto free_targets_out; 214*4bc05954SSeongJae Park } 215*4bc05954SSeongJae Park } 216*4bc05954SSeongJae Park } 217*4bc05954SSeongJae Park 218*4bc05954SSeongJae Park mutex_lock(&ctx->kdamond_lock); 219*4bc05954SSeongJae Park if (ctx->kdamond) { 220*4bc05954SSeongJae Park if (targetid_is_pid(ctx)) 221*4bc05954SSeongJae Park dbgfs_put_pids(targets, nr_targets); 222*4bc05954SSeongJae Park ret = -EBUSY; 223*4bc05954SSeongJae Park goto unlock_out; 224*4bc05954SSeongJae Park } 225*4bc05954SSeongJae Park 226*4bc05954SSeongJae Park err = damon_set_targets(ctx, targets, nr_targets); 227*4bc05954SSeongJae Park if (err) { 228*4bc05954SSeongJae Park if (targetid_is_pid(ctx)) 229*4bc05954SSeongJae Park dbgfs_put_pids(targets, nr_targets); 230*4bc05954SSeongJae Park ret = err; 231*4bc05954SSeongJae Park } 232*4bc05954SSeongJae Park 233*4bc05954SSeongJae Park unlock_out: 234*4bc05954SSeongJae Park mutex_unlock(&ctx->kdamond_lock); 235*4bc05954SSeongJae Park free_targets_out: 236*4bc05954SSeongJae Park kfree(targets); 237*4bc05954SSeongJae Park out: 238*4bc05954SSeongJae Park kfree(kbuf); 239*4bc05954SSeongJae Park return ret; 240*4bc05954SSeongJae Park } 241*4bc05954SSeongJae Park 242*4bc05954SSeongJae Park static int damon_dbgfs_open(struct inode *inode, struct file *file) 243*4bc05954SSeongJae Park { 244*4bc05954SSeongJae Park file->private_data = inode->i_private; 245*4bc05954SSeongJae Park 246*4bc05954SSeongJae Park return nonseekable_open(inode, file); 247*4bc05954SSeongJae Park } 248*4bc05954SSeongJae Park 249*4bc05954SSeongJae Park static const struct file_operations attrs_fops = { 250*4bc05954SSeongJae Park .open = damon_dbgfs_open, 251*4bc05954SSeongJae Park .read = dbgfs_attrs_read, 252*4bc05954SSeongJae Park .write = dbgfs_attrs_write, 253*4bc05954SSeongJae Park }; 254*4bc05954SSeongJae Park 255*4bc05954SSeongJae Park static const struct file_operations target_ids_fops = { 256*4bc05954SSeongJae Park .open = damon_dbgfs_open, 257*4bc05954SSeongJae Park .read = dbgfs_target_ids_read, 258*4bc05954SSeongJae Park .write = dbgfs_target_ids_write, 259*4bc05954SSeongJae Park }; 260*4bc05954SSeongJae Park 261*4bc05954SSeongJae Park static void dbgfs_fill_ctx_dir(struct dentry *dir, struct damon_ctx *ctx) 262*4bc05954SSeongJae Park { 263*4bc05954SSeongJae Park const char * const file_names[] = {"attrs", "target_ids"}; 264*4bc05954SSeongJae Park const struct file_operations *fops[] = {&attrs_fops, &target_ids_fops}; 265*4bc05954SSeongJae Park int i; 266*4bc05954SSeongJae Park 267*4bc05954SSeongJae Park for (i = 0; i < ARRAY_SIZE(file_names); i++) 268*4bc05954SSeongJae Park debugfs_create_file(file_names[i], 0600, dir, ctx, fops[i]); 269*4bc05954SSeongJae Park } 270*4bc05954SSeongJae Park 271*4bc05954SSeongJae Park static int dbgfs_before_terminate(struct damon_ctx *ctx) 272*4bc05954SSeongJae Park { 273*4bc05954SSeongJae Park struct damon_target *t, *next; 274*4bc05954SSeongJae Park 275*4bc05954SSeongJae Park if (!targetid_is_pid(ctx)) 276*4bc05954SSeongJae Park return 0; 277*4bc05954SSeongJae Park 278*4bc05954SSeongJae Park damon_for_each_target_safe(t, next, ctx) { 279*4bc05954SSeongJae Park put_pid((struct pid *)t->id); 280*4bc05954SSeongJae Park damon_destroy_target(t); 281*4bc05954SSeongJae Park } 282*4bc05954SSeongJae Park return 0; 283*4bc05954SSeongJae Park } 284*4bc05954SSeongJae Park 285*4bc05954SSeongJae Park static struct damon_ctx *dbgfs_new_ctx(void) 286*4bc05954SSeongJae Park { 287*4bc05954SSeongJae Park struct damon_ctx *ctx; 288*4bc05954SSeongJae Park 289*4bc05954SSeongJae Park ctx = damon_new_ctx(); 290*4bc05954SSeongJae Park if (!ctx) 291*4bc05954SSeongJae Park return NULL; 292*4bc05954SSeongJae Park 293*4bc05954SSeongJae Park damon_va_set_primitives(ctx); 294*4bc05954SSeongJae Park ctx->callback.before_terminate = dbgfs_before_terminate; 295*4bc05954SSeongJae Park return ctx; 296*4bc05954SSeongJae Park } 297*4bc05954SSeongJae Park 298*4bc05954SSeongJae Park static ssize_t dbgfs_monitor_on_read(struct file *file, 299*4bc05954SSeongJae Park char __user *buf, size_t count, loff_t *ppos) 300*4bc05954SSeongJae Park { 301*4bc05954SSeongJae Park char monitor_on_buf[5]; 302*4bc05954SSeongJae Park bool monitor_on = damon_nr_running_ctxs() != 0; 303*4bc05954SSeongJae Park int len; 304*4bc05954SSeongJae Park 305*4bc05954SSeongJae Park len = scnprintf(monitor_on_buf, 5, monitor_on ? "on\n" : "off\n"); 306*4bc05954SSeongJae Park 307*4bc05954SSeongJae Park return simple_read_from_buffer(buf, count, ppos, monitor_on_buf, len); 308*4bc05954SSeongJae Park } 309*4bc05954SSeongJae Park 310*4bc05954SSeongJae Park static ssize_t dbgfs_monitor_on_write(struct file *file, 311*4bc05954SSeongJae Park const char __user *buf, size_t count, loff_t *ppos) 312*4bc05954SSeongJae Park { 313*4bc05954SSeongJae Park ssize_t ret = count; 314*4bc05954SSeongJae Park char *kbuf; 315*4bc05954SSeongJae Park int err; 316*4bc05954SSeongJae Park 317*4bc05954SSeongJae Park kbuf = user_input_str(buf, count, ppos); 318*4bc05954SSeongJae Park if (IS_ERR(kbuf)) 319*4bc05954SSeongJae Park return PTR_ERR(kbuf); 320*4bc05954SSeongJae Park 321*4bc05954SSeongJae Park /* Remove white space */ 322*4bc05954SSeongJae Park if (sscanf(kbuf, "%s", kbuf) != 1) { 323*4bc05954SSeongJae Park kfree(kbuf); 324*4bc05954SSeongJae Park return -EINVAL; 325*4bc05954SSeongJae Park } 326*4bc05954SSeongJae Park 327*4bc05954SSeongJae Park if (!strncmp(kbuf, "on", count)) 328*4bc05954SSeongJae Park err = damon_start(dbgfs_ctxs, dbgfs_nr_ctxs); 329*4bc05954SSeongJae Park else if (!strncmp(kbuf, "off", count)) 330*4bc05954SSeongJae Park err = damon_stop(dbgfs_ctxs, dbgfs_nr_ctxs); 331*4bc05954SSeongJae Park else 332*4bc05954SSeongJae Park err = -EINVAL; 333*4bc05954SSeongJae Park 334*4bc05954SSeongJae Park if (err) 335*4bc05954SSeongJae Park ret = err; 336*4bc05954SSeongJae Park kfree(kbuf); 337*4bc05954SSeongJae Park return ret; 338*4bc05954SSeongJae Park } 339*4bc05954SSeongJae Park 340*4bc05954SSeongJae Park static const struct file_operations monitor_on_fops = { 341*4bc05954SSeongJae Park .read = dbgfs_monitor_on_read, 342*4bc05954SSeongJae Park .write = dbgfs_monitor_on_write, 343*4bc05954SSeongJae Park }; 344*4bc05954SSeongJae Park 345*4bc05954SSeongJae Park static int __init __damon_dbgfs_init(void) 346*4bc05954SSeongJae Park { 347*4bc05954SSeongJae Park struct dentry *dbgfs_root; 348*4bc05954SSeongJae Park const char * const file_names[] = {"monitor_on"}; 349*4bc05954SSeongJae Park const struct file_operations *fops[] = {&monitor_on_fops}; 350*4bc05954SSeongJae Park int i; 351*4bc05954SSeongJae Park 352*4bc05954SSeongJae Park dbgfs_root = debugfs_create_dir("damon", NULL); 353*4bc05954SSeongJae Park 354*4bc05954SSeongJae Park for (i = 0; i < ARRAY_SIZE(file_names); i++) 355*4bc05954SSeongJae Park debugfs_create_file(file_names[i], 0600, dbgfs_root, NULL, 356*4bc05954SSeongJae Park fops[i]); 357*4bc05954SSeongJae Park dbgfs_fill_ctx_dir(dbgfs_root, dbgfs_ctxs[0]); 358*4bc05954SSeongJae Park 359*4bc05954SSeongJae Park dbgfs_dirs = kmalloc_array(1, sizeof(dbgfs_root), GFP_KERNEL); 360*4bc05954SSeongJae Park if (!dbgfs_dirs) { 361*4bc05954SSeongJae Park debugfs_remove(dbgfs_root); 362*4bc05954SSeongJae Park return -ENOMEM; 363*4bc05954SSeongJae Park } 364*4bc05954SSeongJae Park dbgfs_dirs[0] = dbgfs_root; 365*4bc05954SSeongJae Park 366*4bc05954SSeongJae Park return 0; 367*4bc05954SSeongJae Park } 368*4bc05954SSeongJae Park 369*4bc05954SSeongJae Park /* 370*4bc05954SSeongJae Park * Functions for the initialization 371*4bc05954SSeongJae Park */ 372*4bc05954SSeongJae Park 373*4bc05954SSeongJae Park static int __init damon_dbgfs_init(void) 374*4bc05954SSeongJae Park { 375*4bc05954SSeongJae Park int rc; 376*4bc05954SSeongJae Park 377*4bc05954SSeongJae Park dbgfs_ctxs = kmalloc(sizeof(*dbgfs_ctxs), GFP_KERNEL); 378*4bc05954SSeongJae Park if (!dbgfs_ctxs) 379*4bc05954SSeongJae Park return -ENOMEM; 380*4bc05954SSeongJae Park dbgfs_ctxs[0] = dbgfs_new_ctx(); 381*4bc05954SSeongJae Park if (!dbgfs_ctxs[0]) { 382*4bc05954SSeongJae Park kfree(dbgfs_ctxs); 383*4bc05954SSeongJae Park return -ENOMEM; 384*4bc05954SSeongJae Park } 385*4bc05954SSeongJae Park dbgfs_nr_ctxs = 1; 386*4bc05954SSeongJae Park 387*4bc05954SSeongJae Park rc = __damon_dbgfs_init(); 388*4bc05954SSeongJae Park if (rc) { 389*4bc05954SSeongJae Park kfree(dbgfs_ctxs[0]); 390*4bc05954SSeongJae Park kfree(dbgfs_ctxs); 391*4bc05954SSeongJae Park pr_err("%s: dbgfs init failed\n", __func__); 392*4bc05954SSeongJae Park } 393*4bc05954SSeongJae Park 394*4bc05954SSeongJae Park return rc; 395*4bc05954SSeongJae Park } 396*4bc05954SSeongJae Park 397*4bc05954SSeongJae Park module_init(damon_dbgfs_init); 398